1 // Vistaの効果を有効にするフラグ(不要の場合はコメントアウト)
\r
2 #define USE_VISTA_EFFECTS
\r
4 // Sevenの効果を有効にするフラグ(不要の場合はコメントアウト)
\r
5 #define USE_SEVEN_EFFECTS
\r
8 using System.Runtime.InteropServices;
\r
9 using System.Windows.Forms;
\r
10 using System.Drawing;
\r
12 namespace AppliStation.Util
\r
15 /// Win32ネイティブメソッドを叩いてGUI操作するための関数群のクラス
\r
17 public sealed class NativeMethods
\r
22 private NativeMethods()
\r
31 public enum ProgressBarState
\r
34 /// 通常の状態(PBST_NORMAL)。デフォルトの設定では緑色。
\r
38 /// エラーの状態(PBST_ERROR)。デフォルトの設定では赤色。
\r
42 /// 停止の状態(PBST_PAUSED)。デフォルトの設定では黄色。
\r
48 /// WindowsVista以降向け、プログレスバーステータス(色)を設定する。
\r
50 /// <param name="progBar">対象のプログレスバー</param>
\r
51 /// <param name="state">状態(色)</param>
\r
52 public static void ProgressBar_SetState(ProgressBar progBar, ProgressBarState state)
\r
54 #if USE_VISTA_EFFECTS
\r
56 // SendMessage(progressBar.Handle, PBM_SETSTATE, state, 0);
\r
57 SendMessage(progBar.Handle, 0x410, new IntPtr((int) state), IntPtr.Zero);
\r
58 } catch (Exception) {
\r
63 #region タスクバー上の進捗表示のためのP/Invoke
\r
65 internal enum TBPFLAG
\r
67 TBPF_NOPROGRESS = 0,
\r
68 TBPF_INDETERMINATE = 0x1,
\r
75 [Guid("EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF")]
\r
76 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
\r
77 internal interface ITaskList3
\r
80 void AddTab(IntPtr hWnd);
\r
81 void DeleteTab(IntPtr hWnd);
\r
82 void ActivateTab(IntPtr hWnd);
\r
83 void SetActiveAlt(IntPtr hWnd);
\r
84 void MarkFullscreenWindow(IntPtr hWnd, int fFullscreen);
\r
85 void SetProgressValue(IntPtr hWnd, ulong ullCompleted, ulong ullTotal);
\r
86 void SetProgressState(IntPtr hWnd, TBPFLAG tbpFlags);
\r
87 // more functions follows, but we do not need these.
\r
91 [Guid("56FDF344-FD6D-11d0-958A-006097C9A090")]
\r
92 [ClassInterface(ClassInterfaceType.None)]
\r
93 internal class CTaskbarList
\r
102 /// <param name="form">対象フォーム</param>
\r
103 /// <param name="style">表示スタイル</param>
\r
104 /// <param name="state">ステータス(色)</param>
\r
105 /// <param name="val">プログレスバーの値。0を指定すると進捗表示をしない</param>
\r
106 /// <param name="maximum">プログレスバーの最大値。</param>
\r
107 public static void Form_SetTaskbarProgressParams(Form form, ProgressBarStyle style, ProgressBarState state, ulong val, ulong maximum)
\r
109 #if USE_VISTA_EFFECTS
\r
110 #if USE_SEVEN_EFFECTS
\r
111 ITaskList3 tasklist = null;
\r
114 TBPFLAG tbpFlag = TBPFLAG.TBPF_NOPROGRESS;
\r
116 if (style == ProgressBarStyle.Marquee) {
\r
117 tbpFlag |= TBPFLAG.TBPF_INDETERMINATE;
\r
118 } else if (val > 0 && maximum > 0) {
\r
119 tbpFlag |= TBPFLAG.TBPF_NORMAL;
\r
122 if (state == ProgressBarState.Error) {
\r
123 tbpFlag |= TBPFLAG.TBPF_ERROR;
\r
125 if (state == ProgressBarState.Paused) {
\r
126 tbpFlag |= TBPFLAG.TBPF_PAUSED;
\r
129 tasklist = (ITaskList3) new CTaskbarList();
\r
132 tasklist.SetProgressState(form.Handle, tbpFlag);
\r
133 tasklist.SetProgressValue(form.Handle, val, maximum);
\r
134 } catch (Exception) {
\r
136 if (tasklist != null) {
\r
137 Marshal.ReleaseComObject(tasklist);
\r
147 #region タスクバーおよびタイトルバーのフラッシュ
\r
150 /// タスクバーおよびタイトルバーボタンのフラッシュの設定フラグ
\r
152 public enum FlashFlag : uint {
\r
166 /// タイトルバーとタスクバーボタンを点滅
\r
170 /// Stopが設定されるまで点滅する
\r
174 /// フォアグラウンドの状態になるまで点滅
\r
179 [StructLayout(LayoutKind.Sequential)]
\r
183 public IntPtr hWnd;
\r
184 public FlashFlag dwFlags;
\r
185 public uint uCount;
\r
186 public uint dwTimeout;
\r
190 /// タスクバーおよびタイトルバーボタンを点滅させる
\r
192 /// <param name="form">対象フォーム</param>
\r
193 /// <param name="flag">点滅パラメータフラグ</param>
\r
194 /// <param name="count">点滅回数</param>
\r
195 /// <param name="timeout">点滅の間隔(ミリ秒)</param>
\r
196 /// <returns></returns>
\r
197 public static bool Form_FlashWindow(Form form, FlashFlag flag, uint count, uint timeout)
\r
200 FLASHWINFO info = new FLASHWINFO();
\r
201 info.cbSize = Marshal.SizeOf(typeof(FLASHWINFO));
\r
202 info.hWnd = form.Handle;
\r
203 info.dwFlags = flag;
\r
204 info.uCount = count;
\r
205 info.dwTimeout = timeout;
\r
207 return FlashWindowEx(ref info) == 0;
\r
208 } catch (Exception) {
\r
213 [DllImport("user32.dll")]
\r
214 static extern Int32 FlashWindowEx(ref FLASHWINFO pwfi);
\r
221 /// リストビューにダブルバッファでの描画をするか否かを設定する
\r
223 /// <remarks>マウスでの選択に半透明ツールを採用するか否かもこの設定に依存</remarks>
\r
224 /// <param name="listView">対象のリストビュー</param>
\r
225 /// <param name="bEnable">ダブルバッファでの描画をするとき<code>true</code></param>
\r
226 public static void ListView_SetDoubleBuffer(ListView listView, bool bEnable)
\r
229 // SendMessage(listView.Handle, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER, bEnable? LVS_EX_DOUBLEBUFFER:0);
\r
230 SendMessage(listView.Handle, 0x1036, new IntPtr(0x00010000), new IntPtr((bEnable)? 0x00010000u:0x0u));
\r
231 } catch (Exception) {
\r
236 /// 選択されたアイテムの部分の背景にグラデーションがかかった感じになる、
\r
237 /// Vista以降でのエクスプローラの見た目をListViewに反映させる。
\r
239 /// <remarks>Vista未満のバージョンでは何もしない。</remarks>
\r
240 /// <param name="listView">対象のListView</param>
\r
241 public static void ListView_EnableVistaExplorerTheme(ListView listView)
\r
243 #if USE_VISTA_EFFECTS
\r
245 OperatingSystem os = Environment.OSVersion;
\r
246 if (os.Platform != PlatformID.Win32NT || os.Version.Major < 6) return;
\r
249 SetWindowTheme(listView.Handle, "explorer", null);
\r
250 } catch (Exception) {
\r
256 /// ヘッダに"すべて選択"に似たチェックボックスを作るか否かを指定する
\r
258 /// <remarks>このオプションを設定するとVistaエクスプローラでの「チェックボックスを使用して項目を選択する」と同様の動作になる</remarks>
\r
259 /// <param name="listView">対象のListBox</param>
\r
260 /// <param name="bAutoCheckSelect">チェックボックスを使用して項目を選択するとき<code>true</code></param>
\r
261 public static void ListView_SetAutoCheckSelect(ListView listView, bool bAutoCheckSelect)
\r
263 #if USE_VISTA_EFFECTS
\r
265 // SendMessage(listView.Handle, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_AUTOCHECKSELECT, bAutoCheckSelect?LVS_EX_AUTOCHECKSELECT:0);
\r
266 SendMessage(listView.Handle, 0x1036, new IntPtr(0x08000000), new IntPtr((bAutoCheckSelect)?0x08000000u:0x0u));
\r
267 } catch (Exception) {
\r
272 #region ColumnHeaderのソートの三角印用
\r
274 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
\r
275 private struct HD_ITEM
\r
279 [MarshalAs(UnmanagedType.LPTStr)]public string pszText;
\r
281 public int cchTextMax;
\r
283 [MarshalAs(UnmanagedType.LPTStr)]public string lParam;
\r
284 public int iImage; // index of bitmap in ImageList
\r
289 /// WinXP以降、ソートの矢印を表示
\r
291 /// <param name="listView">対象のListView</param>
\r
292 /// <param name="column">表示する矢印のヘッダ</param>
\r
293 /// <param name="order">ソートの昇順・降順</param>
\r
294 public static void ColumnHeader_SetSortState(ListView listView, int column, SortOrder order)
\r
297 // SendMessage(hWnd, LVM_GETHEADER, NULL, NULL);
\r
298 IntPtr hWnd = SendMessage(listView.Handle, 0x101F, IntPtr.Zero, IntPtr.Zero);
\r
300 HD_ITEM hdi = new HD_ITEM();
\r
301 hdi.mask = 0x0004; // HDI_FORMAT;
\r
302 for (int i = 0; i < listView.Columns.Count; i++) {
\r
303 // SendMessage(hWnd, HDM_GETITEMW, i, &hdi);
\r
304 SendMessage(hWnd, 0x120b, new IntPtr(i), ref hdi);
\r
306 const int HDF_SORTUP = 0x400;
\r
307 const int HDF_SORTDOWN = 0x200;
\r
309 if (i != column || order == SortOrder.None) {
\r
310 hdi.fmt = hdi.fmt & ~(HDF_SORTUP | HDF_SORTDOWN);
\r
311 } else if (order == SortOrder.Ascending) { // 昇順
\r
312 hdi.fmt = hdi.fmt & ~HDF_SORTDOWN | HDF_SORTUP;
\r
313 } else if (order == SortOrder.Descending) { // 降順
\r
314 hdi.fmt = hdi.fmt & ~HDF_SORTUP | HDF_SORTDOWN;
\r
317 // SendMessage(hWnd, HDM_SETITEMW, i, &hdi);
\r
318 SendMessage(hWnd, 0x120c, new IntPtr(i), ref hdi);
\r
320 } catch (Exception) {
\r
327 /// <param name="listView">ListView</param>
\r
328 /// <returns>ヘッダ部のクライアントサイズ</returns>
\r
329 public static Size ColumnHeader_GetSize(ListView listView)
\r
334 // SendMessage(hWnd, LVM_GETHEADER, NULL, NULL);
\r
335 IntPtr hWnd = SendMessage(listView.Handle, 0x101F, IntPtr.Zero, IntPtr.Zero);
\r
336 GetClientRect(hWnd, out lrect);
\r
338 lrect.Left = lrect.Right = lrect.Top = lrect.Bottom = 0;
\r
341 Size size = new Size(lrect.Right - lrect.Left,
\r
342 lrect.Bottom - lrect.Top);
\r
350 #region EnableWindow(コメントアウト)
\r
352 // /// 指定されたコントロール(ウィンドウ)への、
\r
353 // /// キーボード入力およびマウス入力を有効化または無効化
\r
355 // /// <param name="control">対象のコントロールのハンドラ</param>
\r
356 // /// <param name="bEnable">有効にするか無効にするかを指定</param>
\r
357 // /// <returns>直前にウィンドウが無効状態だった場合はtrueを返す</returns>
\r
358 // public static bool Control_EnableWindow(Control ctrl, bool bEnable)
\r
361 // return EnableWindow(ctrl.Handle, bEnable);
\r
363 // ctrl.Enabled = bEnable;
\r
369 // /// 指定されたコントロール(ウィンドウ)への、
\r
370 // /// キーボード入力およびマウス入力を有効化または無効化
\r
372 // /// <param name="control">対象のコントロールのハンドラ</param>
\r
373 // /// <param name="bEnable">有効にするか無効にするかを指定</param>
\r
374 // /// <returns>直前にウィンドウが無効状態だった場合はtrueを返す</returns>
\r
375 // [DllImport("user32.dll")]
\r
376 // public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
\r
379 #region RichTextBox関連
\r
381 [StructLayout(LayoutKind.Sequential)]
\r
382 private struct CHARFORMAT2
\r
385 public uint dwMask;
\r
386 public uint dwEffects;
\r
387 public int yHeight;
\r
388 public int yOffset;
\r
389 public int crTextColor;
\r
390 public byte bCharSet;
\r
391 public byte bPitchAndFamily;
\r
392 [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
\r
393 public char[] szFaceName;
\r
394 public short wWeight;
\r
395 public short sSpacing;
\r
396 public int crBackColor;
\r
398 public uint dwReserved;
\r
399 public short sStyle;
\r
400 public short wKerning;
\r
401 public byte bUnderlineType;
\r
402 public byte bAnimation;
\r
403 public byte bRevAuthor;
\r
404 public byte bReserved1;
\r
408 /// リッチテキストの選択部分に文字フォーマット効果を与える
\r
410 /// <param name="richTextBox">対象のリッチテキストボックス</param>
\r
411 /// <param name="dwMask">有効な文字フォーマット効果</param>
\r
412 /// <param name="dwEffect">文字フォーマット効果のフラグ</param>
\r
413 public static void RichTextBox_SetSelectionFormat(RichTextBox richTextBox, uint dwMask, uint dwEffect)
\r
415 CHARFORMAT2 cfmt = new CHARFORMAT2();
\r
416 cfmt.cbSize = Marshal.SizeOf(typeof(CHARFORMAT2));
\r
417 cfmt.dwMask = dwMask;
\r
418 cfmt.dwEffects = dwEffect;
\r
420 //SendMessage(richTextBox.Handle, EM_SETCHARFORMAT, SCF_SELECTION, ref cfmt);
\r
421 SendMessage(richTextBox.Handle, 0x0444, new IntPtr(0x0001), ref cfmt);
\r
424 /// リッチテキストにテキストリンクを追加する
\r
426 /// <param name="richTextBox">対象のリッチテキストボックス</param>
\r
427 /// <param name="text">追加するテキスト</param>
\r
428 public static void RichTextBox_AddTextLink(RichTextBox richTextBox, string text)
\r
430 int pos = richTextBox.TextLength;
\r
431 richTextBox.Select(pos,0);
\r
432 richTextBox.SelectedText = text;
\r
433 richTextBox.Select(pos, text.Length);
\r
435 // RichTextBox_SetSelectionFormat(richTextBox, CFM_LINK, CFE_LINK);
\r
436 RichTextBox_SetSelectionFormat(richTextBox, 0x00000020, 0x0020);
\r
438 richTextBox.Select(richTextBox.TextLength, 0);
\r
445 [DllImport("shell32.dll")]
\r
446 private static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex);
\r
448 [DllImport("user32.dll", SetLastError=true)]
\r
449 [return: MarshalAs(UnmanagedType.Bool)]
\r
450 private static extern bool DestroyIcon(IntPtr hIcon);
\r
452 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
\r
453 private struct SHSTOCKICONINFO
\r
455 public Int32 cbSize;
\r
456 public IntPtr hIcon;
\r
457 public Int32 iSysImageIndex;
\r
458 public Int32 iIcon;
\r
459 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)] public string path;
\r
462 [DllImport("shell32.dll", CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
\r
463 private static extern void SHGetStockIconInfo(uint siid, uint uFlags, ref SHSTOCKICONINFO sii);
\r
466 /// アイコンファイル(実行ファイル・DLL)を開いてアイコンを作る
\r
468 /// <remarks>内部でコピーされるのでWin32APIのDestroyIconを使わないでいいが、やや遅い動作</remarks>
\r
469 /// <param name="form">ハンドラ</param>
\r
470 /// <param name="lpszExeFileName">対象ファイル</param>
\r
471 /// <param name="nIconIndex">アイコンインデックス</param>
\r
472 /// <returns>生成されたアイコン</returns>
\r
473 public static Icon ExtractIcon(Form form, string lpszExeFileName, uint nIconIndex)
\r
477 if (! System.IO.File.Exists(lpszExeFileName)) {
\r
478 ico = Icon.ExtractAssociatedIcon(lpszExeFileName); // ExtractAssociatedIconに例外を吐いてもらう
\r
480 IntPtr hInst = (form != null)? form.Handle : IntPtr.Zero;
\r
481 IntPtr hIcon = IntPtr.Zero;
\r
484 hIcon = ExtractIcon(hInst, lpszExeFileName, (int) nIconIndex);
\r
485 if ((hIcon != IntPtr.Zero) && (hIcon.ToInt32() != 2)) {
\r
486 ico = (Icon) Icon.FromHandle(hIcon).Clone();
\r
487 DestroyIcon(hIcon);
\r
489 } catch (System.Runtime.InteropServices.COMException) {
\r
490 // ExtraIconのP/Invoke失敗時用
\r
497 /// ユーザ昇格が必要か設定し、設定必要なときシールドアイコンを表示する。
\r
499 /// <param name="button">対象のボタン</param>
\r
500 /// <param name="required">ユーザ昇格が必要か否か、すなわちシールドアイコンを表示するか</param>
\r
501 public static void Button_SetElevationRequiredState(Button button, bool required)
\r
503 #if USE_VISTA_EFFECTS
\r
504 if (Environment.OSVersion.Version.Major >= 6) {
\r
505 button.FlatStyle = FlatStyle.System;
\r
506 // SendMessage(hWnd, BCM_SETSHIELD, 0, required);
\r
507 SendMessage(button.Handle, 0x160C, IntPtr.Zero, new IntPtr((required)? 1u : 0u));
\r
508 } else { // Legacy OS
\r
510 // FlatStyle.System に設定されている場合、Image プロパティに割り当てられているイメージは表示されない対策
\r
511 if (button.FlatStyle == FlatStyle.System) {
\r
512 button.FlatStyle = FlatStyle.Standard;
\r
515 button.TextImageRelation = TextImageRelation.ImageBeforeText;
\r
517 button.ImageAlign = ContentAlignment.MiddleLeft;
\r
518 using (Icon ico = new Icon(SystemIcons.Shield, 16, 16)) {
\r
519 button.Image = ico.ToBitmap();
\r
522 button.Image = null;
\r
524 button.AutoSize = true;
\r
525 #if USE_VISTA_EFFECTS
\r
531 /// シェルのソトックアイコンのハンドラを取得する。
\r
533 /// <param name="siid">ストックID</param>
\r
534 /// <param name="isSmall">アイコンサイズは小さいのであればtrueを指定</param>
\r
535 /// <returns>アイコンのハンドラ。存在しない場合、null</returns>
\r
536 private static IntPtr SHGetStockIconHandle(uint siid, bool isSmall)
\r
538 #if USE_VISTA_EFFECTS
\r
540 SHSTOCKICONINFO sii = new SHSTOCKICONINFO();
\r
541 sii.cbSize = Marshal.SizeOf(typeof(SHSTOCKICONINFO));
\r
542 sii.hIcon = IntPtr.Zero;
\r
544 //SHGetStockIconInfo(siid, SHGFI_ICON | ((isSmall)? SHGFI_SMALLICON : SHGFI_LARGEICON), ref sii);
\r
545 SHGetStockIconInfo(siid, 0x100u | ((isSmall)? 0x1u : 0x0u), ref sii);
\r
548 } catch (Exception) {
\r
549 return IntPtr.Zero;
\r
552 return IntPtr.Zero;
\r
557 /// ユーザ昇格が必要か設定し、設定必要なときシールドアイコンを表示する。
\r
559 /// <param name="label">対象のリンクラベル</param>
\r
560 /// <param name="required">ユーザ昇格が必要か否か、すなわちシールドアイコンを表示するか</param>
\r
561 public static void LinkLabel_SetElevationRequiredState(LinkLabel label, bool required)
\r
564 IntPtr iconHandle = IntPtr.Zero;
\r
566 //SHGetStockIconHandle(SIID_SHIELD, true);
\r
567 iconHandle = SHGetStockIconHandle(77, true);
\r
568 if (iconHandle != IntPtr.Zero) {
\r
569 label.Image = Bitmap.FromHicon(iconHandle);
\r
571 using (Icon ico = new Icon(SystemIcons.Shield, 16, 16)) {
\r
572 label.Image = ico.ToBitmap();
\r
576 label.ImageAlign = ContentAlignment.MiddleLeft;
\r
577 label.Padding = new Padding(label.Image.Width, label.Padding.Top, label.Padding.Right, label.Padding.Bottom);
\r
579 label.Image = null;
\r
580 label.Padding = new Padding(0);
\r
586 [DllImport("user32.dll", CharSet = CharSet.Auto)]
\r
587 internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
\r
589 [DllImport("user32.dll", CharSet=CharSet.Auto)]
\r
590 private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, ref HD_ITEM lParam);
\r
592 [DllImport("user32.dll", CharSet=CharSet.Auto)]
\r
593 private static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, ref CHARFORMAT2 lParam);
\r
595 [DllImport("uxtheme.dll", ExactSpelling=true, CharSet=CharSet.Unicode)]
\r
596 internal static extern int SetWindowTheme(IntPtr hWnd, String pszSubAppName, String pszSubIdList);
\r
599 [StructLayout(LayoutKind.Sequential)]
\r
600 private struct LRECT {
\r
607 [DllImport("user32.dll")]
\r
608 private static extern bool GetClientRect(IntPtr hWnd, out LRECT lpRect);
\r