|
3 | 3 |
|
4 | 4 | using Microsoft.Extensions.Logging; |
5 | 5 | using System.Runtime.InteropServices; |
6 | | -using System.Windows.Forms; |
7 | | -using Vanara.Extensions; |
8 | 6 | using Windows.Win32; |
9 | 7 | using Windows.Win32.Foundation; |
10 | 8 | using Windows.Win32.NetworkManagement.WNet; |
@@ -162,139 +160,59 @@ public bool Open_FileSaveDialog(nint hWnd, bool pickFoldersOnly, string[] filter |
162 | 160 | } |
163 | 161 |
|
164 | 162 | /// <inheritdoc/> |
165 | | - public bool Open_NetworkConnectionDialog(nint hWind, bool hideRestoreConnectionCheckBox = false, bool persistConnectionAtLogon = false, bool readOnlyPath = false, string? remoteNetworkName = null, bool useMostRecentPath = false) |
| 163 | + public unsafe bool Open_NetworkConnectionDialog(nint hWind, bool hideRestoreConnectionCheckBox = false, bool persistConnectionAtLogon = false, bool readOnlyPath = false, string? remoteNetworkName = null, bool useMostRecentPath = false) |
166 | 164 | { |
167 | | - using var dialog = new NetworkConnectionDialog() |
168 | | - { |
169 | | - HideRestoreConnectionCheckBox = hideRestoreConnectionCheckBox, |
170 | | - PersistConnectionAtLogon = persistConnectionAtLogon, |
171 | | - ReadOnlyPath = readOnlyPath, |
172 | | - RemoteNetworkName = remoteNetworkName!, |
173 | | - UseMostRecentPath = useMostRecentPath, |
174 | | - }; |
175 | | - |
176 | | - var window = Win32Helper.Win32Window.FromLong(hWind.ToInt64()); |
| 165 | + NETRESOURCEW netRes = default; |
| 166 | + CONNECTDLGSTRUCTW dialogOptions = default; |
177 | 167 |
|
178 | | - return dialog.ShowDialog(window) == System.Windows.Forms.DialogResult.OK; |
179 | | - } |
| 168 | + dialogOptions.cbStructure = (uint)Marshal.SizeOf(typeof(CONNECTDLGSTRUCTW)); |
| 169 | + netRes.dwType = NET_RESOURCE_TYPE.RESOURCETYPE_DISK; |
180 | 170 |
|
181 | | - private sealed class NetworkConnectionDialog : CommonDialog |
182 | | - { |
183 | | - private NETRESOURCEW netRes = new(); |
184 | | - private CONNECTDLGSTRUCTW dialogOptions; |
| 171 | + if (hideRestoreConnectionCheckBox) |
| 172 | + dialogOptions.dwFlags |= CONNECTDLGSTRUCT_FLAGS.CONNDLG_HIDE_BOX; |
| 173 | + else |
| 174 | + dialogOptions.dwFlags &= ~CONNECTDLGSTRUCT_FLAGS.CONNDLG_HIDE_BOX; |
185 | 175 |
|
186 | | - /// <summary>Initializes a new instance of the <see cref="NetworkConnectionDialog"/> class.</summary> |
187 | | - public NetworkConnectionDialog() |
| 176 | + if (persistConnectionAtLogon) |
188 | 177 | { |
189 | | - dialogOptions.cbStructure = (uint)Marshal.SizeOf(typeof(CONNECTDLGSTRUCTW)); |
190 | | - netRes.dwType = NET_RESOURCE_TYPE.RESOURCETYPE_DISK; |
| 178 | + dialogOptions.dwFlags |= CONNECTDLGSTRUCT_FLAGS.CONNDLG_PERSIST; |
| 179 | + dialogOptions.dwFlags |= CONNECTDLGSTRUCT_FLAGS.CONNDLG_NOT_PERSIST; |
191 | 180 | } |
192 | | - |
193 | | - /// <summary>Gets the connected device number. This value is only valid after successfully running the dialog.</summary> |
194 | | - /// <value>The connected device number. The value is 1 for A:, 2 for B:, 3 for C:, and so on. If the user made a deviceless connection, the value is –1.</value> |
195 | | - [Browsable(false)] |
196 | | - public int ConnectedDeviceNumber => (int)dialogOptions.dwDevNum; |
197 | | - |
198 | | - /// <summary>Gets or sets a value indicating whether to hide the check box allowing the user to restore the connection at logon.</summary> |
199 | | - /// <value><c>true</c> if hiding restore connection check box; otherwise, <c>false</c>.</value> |
200 | | - [DefaultValue(false), Category("Appearance"), Description("Hide the check box allowing the user to restore the connection at logon.")] |
201 | | - public bool HideRestoreConnectionCheckBox |
| 181 | + else |
202 | 182 | { |
203 | | - get => dialogOptions.dwFlags.HasFlag(CONNECTDLGSTRUCT_FLAGS.CONNDLG_HIDE_BOX); |
204 | | - set |
205 | | - { |
206 | | - if (value) |
207 | | - dialogOptions.dwFlags |= CONNECTDLGSTRUCT_FLAGS.CONNDLG_HIDE_BOX; |
208 | | - else |
209 | | - dialogOptions.dwFlags &= ~CONNECTDLGSTRUCT_FLAGS.CONNDLG_HIDE_BOX; |
210 | | - } |
| 183 | + dialogOptions.dwFlags &= ~CONNECTDLGSTRUCT_FLAGS.CONNDLG_PERSIST; |
| 184 | + dialogOptions.dwFlags &= ~CONNECTDLGSTRUCT_FLAGS.CONNDLG_NOT_PERSIST; |
211 | 185 | } |
212 | 186 |
|
213 | | - /// <summary>Gets or sets a value indicating whether restore the connection at logon.</summary> |
214 | | - /// <value><c>true</c> to restore connection at logon; otherwise, <c>false</c>.</value> |
215 | | - [DefaultValue(false), Category("Behavior"), Description("Restore the connection at logon.")] |
216 | | - public bool PersistConnectionAtLogon |
217 | | - { |
218 | | - get => dialogOptions.dwFlags.IsFlagSet(CONNECTDLGSTRUCT_FLAGS.CONNDLG_PERSIST); |
219 | | - set |
220 | | - { |
221 | | - dialogOptions.dwFlags = dialogOptions.dwFlags.SetFlags(CONNECTDLGSTRUCT_FLAGS.CONNDLG_PERSIST, value); |
222 | | - dialogOptions.dwFlags = dialogOptions.dwFlags.SetFlags(CONNECTDLGSTRUCT_FLAGS.CONNDLG_NOT_PERSIST, !value); |
223 | | - } |
224 | | - } |
| 187 | + fixed (char* lpcRemoteName = remoteNetworkName) |
| 188 | + netRes.lpRemoteName = lpcRemoteName; |
225 | 189 |
|
226 | | - /// <summary> |
227 | | - /// Gets or sets a value indicating whether to display a read-only path instead of allowing the user to type in a path. This is only |
228 | | - /// valid if <see cref="RemoteNetworkName"/> is not <see langword="null"/>. |
229 | | - /// </summary> |
230 | | - /// <value><c>true</c> to display a read only path; otherwise, <c>false</c>.</value> |
231 | | - [DefaultValue(false), Category("Appearance"), Description("Display a read-only path instead of allowing the user to type in a path.")] |
232 | | - public bool ReadOnlyPath { get; set; } |
233 | | - |
234 | | - /// <summary>Gets or sets the name of the remote network.</summary> |
235 | | - /// <value>The name of the remote network.</value> |
236 | | - [DefaultValue(null), Category("Behavior"), Description("The value displayed in the path field.")] |
237 | | - public string RemoteNetworkName |
238 | | - { |
239 | | - get => netRes.lpRemoteName.ToString(); |
240 | | - set |
241 | | - { |
242 | | - unsafe |
243 | | - { |
244 | | - fixed (char* lpcRemoteName = value) |
245 | | - netRes.lpRemoteName = lpcRemoteName; |
246 | | - } |
247 | | - } |
248 | | - } |
249 | | - |
250 | | - /// <summary>Gets or sets a value indicating whether to enter the most recently used paths into the combination box.</summary> |
251 | | - /// <value><c>true</c> to use MRU path; otherwise, <c>false</c>.</value> |
252 | | - /// <exception cref="InvalidOperationException">UseMostRecentPath</exception> |
253 | | - [DefaultValue(false), Category("Behavior"), Description("Enter the most recently used paths into the combination box.")] |
254 | | - public bool UseMostRecentPath |
255 | | - { |
256 | | - get => dialogOptions.dwFlags.IsFlagSet(CONNECTDLGSTRUCT_FLAGS.CONNDLG_USE_MRU); |
257 | | - set |
258 | | - { |
259 | | - if (value && !string.IsNullOrEmpty(RemoteNetworkName)) |
260 | | - throw new InvalidOperationException($"{nameof(UseMostRecentPath)} cannot be set to true if {nameof(RemoteNetworkName)} has a value."); |
261 | | - |
262 | | - dialogOptions.dwFlags = dialogOptions.dwFlags.SetFlags(CONNECTDLGSTRUCT_FLAGS.CONNDLG_USE_MRU, value); |
263 | | - } |
264 | | - } |
| 190 | + if (useMostRecentPath && !string.IsNullOrEmpty(remoteNetworkName)) |
| 191 | + throw new InvalidOperationException($"{nameof(useMostRecentPath)} cannot be set to true if {nameof(remoteNetworkName)} has a value."); |
265 | 192 |
|
266 | | - /// <inheritdoc/> |
267 | | - public unsafe override void Reset() |
268 | | - { |
269 | | - dialogOptions.dwDevNum = unchecked((uint)-1); |
270 | | - dialogOptions.dwFlags = 0; |
271 | | - dialogOptions.lpConnRes = null; |
272 | | - ReadOnlyPath = false; |
273 | | - } |
| 193 | + if (useMostRecentPath) |
| 194 | + dialogOptions.dwFlags |= CONNECTDLGSTRUCT_FLAGS.CONNDLG_USE_MRU; |
| 195 | + else |
| 196 | + dialogOptions.dwFlags &= ~CONNECTDLGSTRUCT_FLAGS.CONNDLG_USE_MRU; |
274 | 197 |
|
275 | | - /// <inheritdoc/> |
276 | | - protected unsafe override bool RunDialog(IntPtr hwndOwner) |
277 | | - { |
278 | | - dialogOptions.hwndOwner = new(hwndOwner); |
| 198 | + dialogOptions.hwndOwner = new(hWind); |
279 | 199 |
|
280 | | - fixed (NETRESOURCEW* lpConnRes = &netRes) |
281 | | - dialogOptions.lpConnRes = lpConnRes; |
| 200 | + dialogOptions.lpConnRes = &netRes; |
282 | 201 |
|
283 | | - if (ReadOnlyPath && !string.IsNullOrEmpty(netRes.lpRemoteName.ToString())) |
284 | | - dialogOptions.dwFlags |= CONNECTDLGSTRUCT_FLAGS.CONNDLG_RO_PATH; |
| 202 | + if (readOnlyPath && !string.IsNullOrEmpty(netRes.lpRemoteName.ToString())) |
| 203 | + dialogOptions.dwFlags |= CONNECTDLGSTRUCT_FLAGS.CONNDLG_RO_PATH; |
285 | 204 |
|
286 | | - var result = PInvoke.WNetConnectionDialog1W(ref dialogOptions); |
| 205 | + var result = PInvoke.WNetConnectionDialog1W(ref dialogOptions); |
287 | 206 |
|
288 | | - dialogOptions.lpConnRes = null; |
| 207 | + dialogOptions.lpConnRes = null; |
289 | 208 |
|
290 | | - if ((uint)result == unchecked((uint)-1)) |
291 | | - return false; |
| 209 | + if ((uint)result == unchecked((uint)-1)) |
| 210 | + return false; |
292 | 211 |
|
293 | | - if (result == 0) |
294 | | - throw new Win32Exception("Cannot display dialog"); |
| 212 | + if (result == 0) |
| 213 | + throw new Win32Exception("Cannot display dialog"); |
295 | 214 |
|
296 | | - return true; |
297 | | - } |
| 215 | + return true; |
298 | 216 | } |
299 | 217 | } |
300 | 218 | } |
0 commit comments