革博士程序V1仓库
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

122 řádky
4.8 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Windows.Forms;
  8. namespace LeatherApp.Utils
  9. {
  10. public class FolderUtil
  11. {
  12. /// <summary>
  13. /// Using title text to look for the top level dialog window is fragile.
  14. /// In particular, this will fail in non-English applications.
  15. /// </summary>
  16. const string _topLevelSearchString = "Browse For Folder";
  17. /// <summary>
  18. /// These should be more robust. We find the correct child controls in the dialog
  19. /// by using the GetDlgItem method, rather than the FindWindow(Ex) method,
  20. /// because the dialog item IDs should be constant.
  21. /// </summary>
  22. const int _dlgItemBrowseControl = 0;
  23. const int _dlgItemTreeView = 100;
  24. [DllImport("user32.dll", SetLastError = true)]
  25. static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
  26. [DllImport("user32.dll")]
  27. static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);
  28. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  29. static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
  30. /// <summary>
  31. /// Some of the messages that the Tree View control will respond to
  32. /// </summary>
  33. private const int TV_FIRST = 0x1100;
  34. private const int TVM_SELECTITEM = (TV_FIRST + 11);
  35. private const int TVM_GETNEXTITEM = (TV_FIRST + 10);
  36. private const int TVM_GETITEM = (TV_FIRST + 12);
  37. private const int TVM_ENSUREVISIBLE = (TV_FIRST + 20);
  38. /// <summary>
  39. /// Constants used to identity specific items in the Tree View control
  40. /// </summary>
  41. private const int TVGN_ROOT = 0x0;
  42. private const int TVGN_NEXT = 0x1;
  43. private const int TVGN_CHILD = 0x4;
  44. private const int TVGN_FIRSTVISIBLE = 0x5;
  45. private const int TVGN_NEXTVISIBLE = 0x6;
  46. private const int TVGN_CARET = 0x9;
  47. /// <summary>
  48. /// Calling this method is identical to calling the ShowDialog method of the provided
  49. /// FolderBrowserDialog, except that an attempt will be made to scroll the Tree View
  50. /// to make the currently selected folder visible in the dialog window.
  51. /// </summary>
  52. /// <param name="dlg"></param>
  53. /// <param name="parent"></param>
  54. /// <returns></returns>
  55. public static DialogResult ShowFolderBrowser(FolderBrowserDialog dlg, IWin32Window parent = null)
  56. {
  57. DialogResult result = DialogResult.Cancel;
  58. int retries = 10;
  59. using (Timer t = new Timer())
  60. {
  61. t.Tick += (s, a) =>
  62. {
  63. if (retries > 0)
  64. {
  65. --retries;
  66. IntPtr hwndDlg = FindWindow((string)null, _topLevelSearchString);
  67. if (hwndDlg != IntPtr.Zero)
  68. {
  69. IntPtr hwndFolderCtrl = GetDlgItem(hwndDlg, _dlgItemBrowseControl);
  70. if (hwndFolderCtrl != IntPtr.Zero)
  71. {
  72. IntPtr hwndTV = GetDlgItem(hwndFolderCtrl, _dlgItemTreeView);
  73. if (hwndTV != IntPtr.Zero)
  74. {
  75. IntPtr item = SendMessage(hwndTV, (uint)TVM_GETNEXTITEM, new IntPtr(TVGN_CARET), IntPtr.Zero);
  76. if (item != IntPtr.Zero)
  77. {
  78. SendMessage(hwndTV, TVM_ENSUREVISIBLE, IntPtr.Zero, item);
  79. retries = 0;
  80. t.Stop();
  81. }
  82. }
  83. }
  84. }
  85. }
  86. else
  87. {
  88. //
  89. // We failed to find the Tree View control.
  90. //
  91. // As a fall back (and this is an UberUgly hack), we will send
  92. // some fake keystrokes to the application in an attempt to force
  93. // the Tree View to scroll to the selected item.
  94. //
  95. t.Stop();
  96. SendKeys.Send("{TAB}{TAB}{DOWN}{DOWN}{UP}{UP}");
  97. }
  98. };
  99. t.Interval = 10;
  100. t.Start();
  101. result = dlg.ShowDialog(parent);
  102. }
  103. return result;
  104. }
  105. }
  106. }