// Vistaの効果を有効にするフラグ(不要の場合はコメントアウト)
#define USE_VISTA_EFFECTS
// Sevenの効果を有効にするフラグ(不要の場合はコメントアウト)
#define USE_SEVEN_EFFECTS
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
namespace AppliStation.Util
{
///
/// Win32ネイティブメソッドを叩いてGUI操作するための関数群のクラス
///
public sealed class NativeMethods
{
///
/// 呼び出し禁止
///
private NativeMethods()
{
}
#region 進捗の表示
///
/// プログレスバーステータス(色)
///
public enum ProgressBarState
{
///
/// 通常の状態(PBST_NORMAL)。デフォルトの設定では緑色。
///
Normal = 0,
///
/// エラーの状態(PBST_ERROR)。デフォルトの設定では赤色。
///
Error = 1,
///
/// 停止の状態(PBST_PAUSED)。デフォルトの設定では黄色。
///
Paused = 2,
}
///
/// WindowsVista以降向け、プログレスバーステータス(色)を設定する。
///
/// 対象のプログレスバー
/// 状態(色)
public static void ProgressBar_SetState(ProgressBar progBar, ProgressBarState state)
{
#if USE_VISTA_EFFECTS
try {
// SendMessage(progressBar.Handle, PBM_SETSTATE, state, 0);
SendMessage(progBar.Handle, 0x410, new IntPtr((int) state), IntPtr.Zero);
} catch (Exception) {
}
#endif
}
#region タスクバー上の進捗表示のためのP/Invoke
internal enum TBPFLAG
{
TBPF_NOPROGRESS = 0,
TBPF_INDETERMINATE = 0x1,
TBPF_NORMAL = 0x2,
TBPF_ERROR = 0x4,
TBPF_PAUSED = 0x8,
}
[ComImport()]
[Guid("EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ITaskList3
{
void HrInit();
void AddTab(IntPtr hWnd);
void DeleteTab(IntPtr hWnd);
void ActivateTab(IntPtr hWnd);
void SetActiveAlt(IntPtr hWnd);
void MarkFullscreenWindow(IntPtr hWnd, int fFullscreen);
void SetProgressValue(IntPtr hWnd, ulong ullCompleted, ulong ullTotal);
void SetProgressState(IntPtr hWnd, TBPFLAG tbpFlags);
// more functions follows, but we do not need these.
}
[ComImport()]
[Guid("56FDF344-FD6D-11d0-958A-006097C9A090")]
[ClassInterface(ClassInterfaceType.None)]
internal class CTaskbarList
{
}
#endregion
///
/// タスクバに進捗を設定する。
///
/// 対象フォーム
/// 表示スタイル
/// ステータス(色)
/// プログレスバーの値。0を指定すると進捗表示をしない
/// プログレスバーの最大値。
public static void Form_SetTaskbarProgressParams(Form form, ProgressBarStyle style, ProgressBarState state, ulong val, ulong maximum)
{
#if USE_VISTA_EFFECTS
#if USE_SEVEN_EFFECTS
ITaskList3 tasklist = null;
try {
TBPFLAG tbpFlag = TBPFLAG.TBPF_NOPROGRESS;
if (style == ProgressBarStyle.Marquee) {
tbpFlag |= TBPFLAG.TBPF_INDETERMINATE;
} else if (val > 0 && maximum > 0) {
tbpFlag |= TBPFLAG.TBPF_NORMAL;
}
if (state == ProgressBarState.Error) {
tbpFlag |= TBPFLAG.TBPF_ERROR;
}
if (state == ProgressBarState.Paused) {
tbpFlag |= TBPFLAG.TBPF_PAUSED;
}
tasklist = (ITaskList3) new CTaskbarList();
tasklist.HrInit();
tasklist.SetProgressState(form.Handle, tbpFlag);
tasklist.SetProgressValue(form.Handle, val, maximum);
} catch (Exception) {
} finally {
if (tasklist != null) {
Marshal.ReleaseComObject(tasklist);
tasklist = null;
}
}
#endif
#endif
}
#endregion
#region タスクバーおよびタイトルバーのフラッシュ
///
/// タスクバーおよびタイトルバーボタンのフラッシュの設定フラグ
///
public enum FlashFlag : uint {
///
/// 点滅の停止
///
Stop = 0,
///
/// タイトルバーを点滅
///
Caption = 1,
///
/// タスクバーボタンを点滅
///
Tray = 2,
///
/// タイトルバーとタスクバーボタンを点滅
///
All = 3,
///
/// Stopが設定されるまで点滅する
///
Timer = 4,
///
/// フォアグラウンドの状態になるまで点滅
///
TimerNoFG = 12,
}
[StructLayout(LayoutKind.Sequential)]
struct FLASHWINFO
{
public int cbSize;
public IntPtr hWnd;
public FlashFlag dwFlags;
public uint uCount;
public uint dwTimeout;
}
///
/// タスクバーおよびタイトルバーボタンを点滅させる
///
/// 対象フォーム
/// 点滅パラメータフラグ
/// 点滅回数
/// 点滅の間隔(ミリ秒)
///
public static bool Form_FlashWindow(Form form, FlashFlag flag, uint count, uint timeout)
{
try {
FLASHWINFO info = new FLASHWINFO();
info.cbSize = Marshal.SizeOf(typeof(FLASHWINFO));
info.hWnd = form.Handle;
info.dwFlags = flag;
info.uCount = count;
info.dwTimeout = timeout;
return FlashWindowEx(ref info) == 0;
} catch (Exception) {
return false;
}
}
[DllImport("user32.dll")]
static extern Int32 FlashWindowEx(ref FLASHWINFO pwfi);
#endregion
#region ListView関連
///
/// リストビューにダブルバッファでの描画をするか否かを設定する
///
/// マウスでの選択に半透明ツールを採用するか否かもこの設定に依存
/// 対象のリストビュー
/// ダブルバッファでの描画をするときtrue
public static void ListView_SetDoubleBuffer(ListView listView, bool bEnable)
{
try {
// SendMessage(listView.Handle, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER, bEnable? LVS_EX_DOUBLEBUFFER:0);
SendMessage(listView.Handle, 0x1036, new IntPtr(0x00010000), new IntPtr((bEnable)? 0x00010000u:0x0u));
} catch (Exception) {
}
}
///
/// 選択されたアイテムの部分の背景にグラデーションがかかった感じになる、
/// Vista以降でのエクスプローラの見た目をListViewに反映させる。
///
/// Vista未満のバージョンでは何もしない。
/// 対象のListView
public static void ListView_EnableVistaExplorerTheme(ListView listView)
{
#if USE_VISTA_EFFECTS
// Vista未満はなにもしない
OperatingSystem os = Environment.OSVersion;
if (os.Platform != PlatformID.Win32NT || os.Version.Major < 6) return;
try {
SetWindowTheme(listView.Handle, "explorer", null);
} catch (Exception) {
}
#endif
}
///
/// ヘッダに"すべて選択"に似たチェックボックスを作るか否かを指定する
///
/// このオプションを設定するとVistaエクスプローラでの「チェックボックスを使用して項目を選択する」と同様の動作になる
/// 対象のListBox
/// チェックボックスを使用して項目を選択するときtrue
public static void ListView_SetAutoCheckSelect(ListView listView, bool bAutoCheckSelect)
{
#if USE_VISTA_EFFECTS
try {
// SendMessage(listView.Handle, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_AUTOCHECKSELECT, bAutoCheckSelect?LVS_EX_AUTOCHECKSELECT:0);
SendMessage(listView.Handle, 0x1036, new IntPtr(0x08000000), new IntPtr((bAutoCheckSelect)?0x08000000u:0x0u));
} catch (Exception) {
}
#endif
}
#region ColumnHeaderのソートの三角印用
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
private struct HD_ITEM
{
public uint mask;
public int cxy;
[MarshalAs(UnmanagedType.LPTStr)]public string pszText;
public IntPtr hbm;
public int cchTextMax;
public int fmt;
[MarshalAs(UnmanagedType.LPTStr)]public string lParam;
public int iImage; // index of bitmap in ImageList
public int iOrder;
}
///
/// WinXP以降、ソートの矢印を表示
///
/// 対象のListView
/// 表示する矢印のヘッダ
/// ソートの昇順・降順
public static void ColumnHeader_SetSortState(ListView listView, int column, SortOrder order)
{
try {
// SendMessage(hWnd, LVM_GETHEADER, NULL, NULL);
IntPtr hWnd = SendMessage(listView.Handle, 0x101F, IntPtr.Zero, IntPtr.Zero);
HD_ITEM hdi = new HD_ITEM();
hdi.mask = 0x0004; // HDI_FORMAT;
for (int i = 0; i < listView.Columns.Count; i++) {
// SendMessage(hWnd, HDM_GETITEMW, i, &hdi);
SendMessage(hWnd, 0x120b, new IntPtr(i), ref hdi);
const int HDF_SORTUP = 0x400;
const int HDF_SORTDOWN = 0x200;
if (i != column || order == SortOrder.None) {
hdi.fmt = hdi.fmt & ~(HDF_SORTUP | HDF_SORTDOWN);
} else if (order == SortOrder.Ascending) { // 昇順
hdi.fmt = hdi.fmt & ~HDF_SORTDOWN | HDF_SORTUP;
} else if (order == SortOrder.Descending) { // 降順
hdi.fmt = hdi.fmt & ~HDF_SORTUP | HDF_SORTDOWN;
}
// SendMessage(hWnd, HDM_SETITEMW, i, &hdi);
SendMessage(hWnd, 0x120c, new IntPtr(i), ref hdi);
}
} catch (Exception) {
}
}
///
/// ヘッダ部のサイズを返す
///
/// ListView
/// ヘッダ部のクライアントサイズ
public static Size ColumnHeader_GetSize(ListView listView)
{
LRECT lrect;
try {
// SendMessage(hWnd, LVM_GETHEADER, NULL, NULL);
IntPtr hWnd = SendMessage(listView.Handle, 0x101F, IntPtr.Zero, IntPtr.Zero);
GetClientRect(hWnd, out lrect);
} catch {
lrect.Left = lrect.Right = lrect.Top = lrect.Bottom = 0;
}
Size size = new Size(lrect.Right - lrect.Left,
lrect.Bottom - lrect.Top);
return size;
}
#endregion
#endregion
#region EnableWindow(コメントアウト)
// ///
// /// 指定されたコントロール(ウィンドウ)への、
// /// キーボード入力およびマウス入力を有効化または無効化
// ///
// /// 対象のコントロールのハンドラ
// /// 有効にするか無効にするかを指定
// /// 直前にウィンドウが無効状態だった場合はtrueを返す
// public static bool Control_EnableWindow(Control ctrl, bool bEnable)
// {
// try {
// return EnableWindow(ctrl.Handle, bEnable);
// } catch {
// ctrl.Enabled = bEnable;
// return true;
// }
// }
//
// ///
// /// 指定されたコントロール(ウィンドウ)への、
// /// キーボード入力およびマウス入力を有効化または無効化
// ///
// /// 対象のコントロールのハンドラ
// /// 有効にするか無効にするかを指定
// /// 直前にウィンドウが無効状態だった場合はtrueを返す
// [DllImport("user32.dll")]
// public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
#endregion
#region RichTextBox関連
[StructLayout(LayoutKind.Sequential)]
private struct CHARFORMAT2
{
public int cbSize;
public uint dwMask;
public uint dwEffects;
public int yHeight;
public int yOffset;
public int crTextColor;
public byte bCharSet;
public byte bPitchAndFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public char[] szFaceName;
public short wWeight;
public short sSpacing;
public int crBackColor;
public int LCID;
public uint dwReserved;
public short sStyle;
public short wKerning;
public byte bUnderlineType;
public byte bAnimation;
public byte bRevAuthor;
public byte bReserved1;
}
///
/// リッチテキストの選択部分に文字フォーマット効果を与える
///
/// 対象のリッチテキストボックス
/// 有効な文字フォーマット効果
/// 文字フォーマット効果のフラグ
public static void RichTextBox_SetSelectionFormat(RichTextBox richTextBox, uint dwMask, uint dwEffect)
{
CHARFORMAT2 cfmt = new CHARFORMAT2();
cfmt.cbSize = Marshal.SizeOf(typeof(CHARFORMAT2));
cfmt.dwMask = dwMask;
cfmt.dwEffects = dwEffect;
//SendMessage(richTextBox.Handle, EM_SETCHARFORMAT, SCF_SELECTION, ref cfmt);
SendMessage(richTextBox.Handle, 0x0444, new IntPtr(0x0001), ref cfmt);
}
///
/// リッチテキストにテキストリンクを追加する
///
/// 対象のリッチテキストボックス
/// 追加するテキスト
public static void RichTextBox_AddTextLink(RichTextBox richTextBox, string text)
{
int pos = richTextBox.TextLength;
richTextBox.Select(pos,0);
richTextBox.SelectedText = text;
richTextBox.Select(pos, text.Length);
// RichTextBox_SetSelectionFormat(richTextBox, CFM_LINK, CFE_LINK);
RichTextBox_SetSelectionFormat(richTextBox, 0x00000020, 0x0020);
richTextBox.Select(richTextBox.TextLength, 0);
}
#endregion
#region アイコン関連
[DllImport("shell32.dll")]
private static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex);
[DllImport("user32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DestroyIcon(IntPtr hIcon);
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
private struct SHSTOCKICONINFO
{
public Int32 cbSize;
public IntPtr hIcon;
public Int32 iSysImageIndex;
public Int32 iIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)] public string path;
}
[DllImport("shell32.dll", CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
private static extern void SHGetStockIconInfo(uint siid, uint uFlags, ref SHSTOCKICONINFO sii);
///
/// アイコンファイル(実行ファイル・DLL)を開いてアイコンを作る
///
/// 内部でコピーされるのでWin32APIのDestroyIconを使わないでいいが、やや遅い動作
/// ハンドラ
/// 対象ファイル
/// アイコンインデックス
/// 生成されたアイコン
public static Icon ExtractIcon(Form form, string lpszExeFileName, uint nIconIndex)
{
Icon ico = null;
if (! System.IO.File.Exists(lpszExeFileName)) {
ico = Icon.ExtractAssociatedIcon(lpszExeFileName); // ExtractAssociatedIconに例外を吐いてもらう
} else {
IntPtr hInst = (form != null)? form.Handle : IntPtr.Zero;
IntPtr hIcon = IntPtr.Zero;
try {
hIcon = ExtractIcon(hInst, lpszExeFileName, (int) nIconIndex);
if ((hIcon != IntPtr.Zero) && (hIcon.ToInt32() != 2)) {
ico = (Icon) Icon.FromHandle(hIcon).Clone();
DestroyIcon(hIcon);
}
} catch (System.Runtime.InteropServices.COMException) {
// ExtraIconのP/Invoke失敗時用
}
}
return ico;
}
///
/// ユーザ昇格が必要か設定し、設定必要なときシールドアイコンを表示する。
///
/// 対象のボタン
/// ユーザ昇格が必要か否か、すなわちシールドアイコンを表示するか
public static void Button_SetElevationRequiredState(Button button, bool required)
{
#if USE_VISTA_EFFECTS
if (Environment.OSVersion.Version.Major >= 6) {
button.FlatStyle = FlatStyle.System;
// SendMessage(hWnd, BCM_SETSHIELD, 0, required);
SendMessage(button.Handle, 0x160C, IntPtr.Zero, new IntPtr((required)? 1u : 0u));
} else { // Legacy OS
#endif
// FlatStyle.System に設定されている場合、Image プロパティに割り当てられているイメージは表示されない対策
if (button.FlatStyle == FlatStyle.System) {
button.FlatStyle = FlatStyle.Standard;
}
button.TextImageRelation = TextImageRelation.ImageBeforeText;
if (required) {
button.ImageAlign = ContentAlignment.MiddleLeft;
using (Icon ico = new Icon(SystemIcons.Shield, 16, 16)) {
button.Image = ico.ToBitmap();
}
} else {
button.Image = null;
}
button.AutoSize = true;
#if USE_VISTA_EFFECTS
}
#endif
}
///
/// シェルのソトックアイコンのハンドラを取得する。
///
/// ストックID
/// アイコンサイズは小さいのであればtrueを指定
/// アイコンのハンドラ。存在しない場合、null
private static IntPtr SHGetStockIconHandle(uint siid, bool isSmall)
{
#if USE_VISTA_EFFECTS
try {
SHSTOCKICONINFO sii = new SHSTOCKICONINFO();
sii.cbSize = Marshal.SizeOf(typeof(SHSTOCKICONINFO));
sii.hIcon = IntPtr.Zero;
//SHGetStockIconInfo(siid, SHGFI_ICON | ((isSmall)? SHGFI_SMALLICON : SHGFI_LARGEICON), ref sii);
SHGetStockIconInfo(siid, 0x100u | ((isSmall)? 0x1u : 0x0u), ref sii);
return sii.hIcon;
} catch (Exception) {
return IntPtr.Zero;
}
#else
return IntPtr.Zero;
#endif
}
///
/// ユーザ昇格が必要か設定し、設定必要なときシールドアイコンを表示する。
///
/// 対象のリンクラベル
/// ユーザ昇格が必要か否か、すなわちシールドアイコンを表示するか
public static void LinkLabel_SetElevationRequiredState(LinkLabel label, bool required)
{
if (required) {
IntPtr iconHandle = IntPtr.Zero;
//SHGetStockIconHandle(SIID_SHIELD, true);
iconHandle = SHGetStockIconHandle(77, true);
if (iconHandle != IntPtr.Zero) {
label.Image = Bitmap.FromHicon(iconHandle);
} else {
using (Icon ico = new Icon(SystemIcons.Shield, 16, 16)) {
label.Image = ico.ToBitmap();
}
}
label.ImageAlign = ContentAlignment.MiddleLeft;
label.Padding = new Padding(label.Image.Width, label.Padding.Top, label.Padding.Right, label.Padding.Bottom);
} else {
label.Image = null;
label.Padding = new Padding(0);
}
}
#endregion
[DllImport("user32.dll", CharSet=CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, ref HD_ITEM lParam);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, ref CHARFORMAT2 lParam);
[DllImport("uxtheme.dll", ExactSpelling=true, CharSet=CharSet.Unicode)]
internal static extern int SetWindowTheme(IntPtr hWnd, String pszSubAppName, String pszSubIdList);
[Serializable]
[StructLayout(LayoutKind.Sequential)]
private struct LRECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll")]
private static extern bool GetClientRect(IntPtr hWnd, out LRECT lpRect);
}
}