// 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); } }