ClassicFileDialog.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. using System;
  2. using System.Reflection;
  3. using System.Windows.Forms;
  4. namespace PaintDotNet.SystemLayer
  5. {
  6. public abstract class ClassicFileDialog : IFileDialog
  7. {
  8. private FileDialog fileDialog;
  9. protected FileDialog FileDialog
  10. {
  11. get
  12. {
  13. return this.fileDialog;
  14. }
  15. }
  16. public bool CheckPathExists
  17. {
  18. get
  19. {
  20. return this.fileDialog.CheckPathExists;
  21. }
  22. set
  23. {
  24. this.fileDialog.CheckPathExists = value;
  25. }
  26. }
  27. public bool DereferenceLinks
  28. {
  29. get
  30. {
  31. return this.fileDialog.DereferenceLinks;
  32. }
  33. set
  34. {
  35. this.fileDialog.DereferenceLinks = value;
  36. }
  37. }
  38. public string Filter
  39. {
  40. get
  41. {
  42. return this.fileDialog.Filter;
  43. }
  44. set
  45. {
  46. this.fileDialog.Filter = value;
  47. }
  48. }
  49. public int FilterIndex
  50. {
  51. get
  52. {
  53. return this.fileDialog.FilterIndex;
  54. }
  55. set
  56. {
  57. this.fileDialog.FilterIndex = value;
  58. }
  59. }
  60. public string InitialDirectory
  61. {
  62. get
  63. {
  64. return this.fileDialog.InitialDirectory;
  65. }
  66. set
  67. {
  68. this.fileDialog.InitialDirectory = value;
  69. }
  70. }
  71. public string Title
  72. {
  73. set
  74. {
  75. this.fileDialog.Title = value;
  76. }
  77. }
  78. // Must verify this still works with each new revision of .NET
  79. // This is a major hack to get the .NET's OFD to show with Thumbnail view by default!
  80. // Luckily for us this is a covert hack, and not one where we're working around a bug
  81. // in the framework or OS.
  82. // This hack works by retrieving a private property of the OFD class after it has shown
  83. // the dialog box.
  84. // Based off code found here: http://vbnet.mvps.org/index.html?code/hooks/fileopensavedlghooklvview.htm
  85. private static void EnableThumbnailView(FileDialog ofd)
  86. {
  87. try
  88. {
  89. Type ofdType = typeof(FileDialog);
  90. FieldInfo fi = ofdType.GetField("dialogHWnd", BindingFlags.Instance | BindingFlags.NonPublic);
  91. if (fi != null)
  92. {
  93. object dialogHWndObject = fi.GetValue(ofd);
  94. IntPtr dialogHWnd = (IntPtr)dialogHWndObject;
  95. IntPtr hwndLV = SafeNativeMethods.FindWindowExW(dialogHWnd, IntPtr.Zero, "SHELLDLL_DefView", null);
  96. if (hwndLV != IntPtr.Zero)
  97. {
  98. SafeNativeMethods.SendMessageW(hwndLV, NativeConstants.WM_COMMAND, new IntPtr(NativeConstants.SHVIEW_THUMBNAIL), IntPtr.Zero);
  99. }
  100. }
  101. }
  102. catch (Exception)
  103. {
  104. // Ignore.
  105. }
  106. }
  107. public DialogResult ShowDialog(IWin32Window owner, IFileDialogUICallbacks uiCallbacks)
  108. {
  109. Control ownerAsControl = owner as Control;
  110. if (uiCallbacks == null)
  111. {
  112. throw new ArgumentNullException("uiCallbacks");
  113. }
  114. Cursor.Current = Cursors.WaitCursor;
  115. if ((Control.ModifierKeys & Keys.Shift) != 0)
  116. {
  117. UI.InvokeThroughModalTrampoline(
  118. owner,
  119. delegate (IWin32Window modalOwner)
  120. {
  121. while ((Control.ModifierKeys & Keys.Shift) != 0)
  122. {
  123. System.Threading.Thread.Sleep(1);
  124. Application.DoEvents();
  125. }
  126. });
  127. }
  128. Cursor.Current = Cursors.Default;
  129. DialogResult result = DialogResult.Cancel;
  130. UI.InvokeThroughModalTrampoline(
  131. owner,
  132. delegate (IWin32Window modalOwner)
  133. {
  134. if (ownerAsControl != null && ownerAsControl.IsHandleCreated)
  135. {
  136. ownerAsControl.BeginInvoke(new Procedure<FileDialog>(EnableThumbnailView), new object[] { this.fileDialog });
  137. }
  138. result = this.fileDialog.ShowDialog(modalOwner);
  139. });
  140. return result;
  141. }
  142. protected ClassicFileDialog(FileDialog fileDialog)
  143. {
  144. this.fileDialog = fileDialog;
  145. this.fileDialog.RestoreDirectory = true;
  146. this.fileDialog.ShowHelp = false;
  147. this.fileDialog.ValidateNames = true;
  148. }
  149. ~ClassicFileDialog()
  150. {
  151. Dispose(false);
  152. }
  153. public void Dispose()
  154. {
  155. Dispose(true);
  156. GC.SuppressFinalize(this);
  157. }
  158. protected virtual void Dispose(bool disposing)
  159. {
  160. if (disposing)
  161. {
  162. if (this.fileDialog != null)
  163. {
  164. this.fileDialog.Dispose();
  165. this.fileDialog = null;
  166. }
  167. }
  168. }
  169. }
  170. }