private bool RunDialogOld(IntPtr hWndOwner) { NativeMethods.WndProc hookProcPtr = new NativeMethods.WndProc(this.HookProc); NativeMethods.OPENFILENAME_I ofn = new NativeMethods.OPENFILENAME_I(); try { charBuffer = CharBuffer.CreateBuffer(FILEBUFSIZE); if (fileNames != null) { charBuffer.PutString(fileNames[0]); } ofn.lStructSize = Marshal.SizeOf(typeof(NativeMethods.OPENFILENAME_I)); // Degrade to the older style dialog if we're not on Win2K. // We do this by setting the struct size to a different value // if (Environment.OSVersion.Platform != System.PlatformID.Win32NT || Environment.OSVersion.Version.Major < 5) { ofn.lStructSize = 0x4C; } ofn.hwndOwner = hWndOwner; ofn.hInstance = Instance; ofn.lpstrFilter = MakeFilterString(filter, this.DereferenceLinks); ofn.nFilterIndex = filterIndex; ofn.lpstrFile = charBuffer.AllocCoTaskMem(); ofn.nMaxFile = FILEBUFSIZE; ofn.lpstrInitialDir = initialDir; ofn.lpstrTitle = title; ofn.Flags = Options | (NativeMethods.OFN_EXPLORER | NativeMethods.OFN_ENABLEHOOK | NativeMethods.OFN_ENABLESIZING); ofn.lpfnHook = hookProcPtr; ofn.FlagsEx = NativeMethods.OFN_USESHELLITEM; if (defaultExt != null && AddExtension) { ofn.lpstrDefExt = defaultExt; } //Security checks happen here return(RunFileDialog(ofn)); } finally { charBuffer = null; if (ofn.lpstrFile != IntPtr.Zero) { Marshal.FreeCoTaskMem(ofn.lpstrFile); } } }
protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam) { if (msg == NativeMethods.WM_NOTIFY) { dialogHWnd = UnsafeNativeMethods.GetParent(new HandleRef(null, hWnd)); try { UnsafeNativeMethods.OFNOTIFY notify = (UnsafeNativeMethods.OFNOTIFY)UnsafeNativeMethods.PtrToStructure(lparam, typeof(UnsafeNativeMethods.OFNOTIFY)); switch (notify.hdr_code) { case -601: /* CDN_INITDONE */ MoveToScreenCenter(dialogHWnd); break; case -602: /* CDN_SELCHANGE */ NativeMethods.OPENFILENAME_I ofn = (NativeMethods.OPENFILENAME_I)UnsafeNativeMethods.PtrToStructure(notify.lpOFN, typeof(NativeMethods.OPENFILENAME_I)); // Get the buffer size required to store the selected file names. int sizeNeeded = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, dialogHWnd), 1124 /*CDM_GETSPEC*/, System.IntPtr.Zero, System.IntPtr.Zero); if (sizeNeeded > ofn.nMaxFile) { // A bigger buffer is required. try { int newBufferSize = sizeNeeded + (FILEBUFSIZE / 4); // Allocate new buffer CharBuffer charBufferTmp = CharBuffer.CreateBuffer(newBufferSize); IntPtr newBuffer = charBufferTmp.AllocCoTaskMem(); // Free old buffer Marshal.FreeCoTaskMem(ofn.lpstrFile); // Substitute buffer ofn.lpstrFile = newBuffer; ofn.nMaxFile = newBufferSize; this.charBuffer = charBufferTmp; Marshal.StructureToPtr(ofn, notify.lpOFN, true); Marshal.StructureToPtr(notify, lparam, true); } catch { // intentionaly not throwing here. } } this.ignoreSecondFileOkNotification = false; break; case -604: /* CDN_SHAREVIOLATION */ // See VS Whidbey 95342. When the selected file is locked for writing, // we get this notification followed by *two* CDN_FILEOK notifications. this.ignoreSecondFileOkNotification = true; // We want to ignore the second CDN_FILEOK this.okNotificationCount = 0; // to avoid a second prompt by PromptFileOverwrite. break; case -606: /* CDN_FILEOK */ if (this.ignoreSecondFileOkNotification) { // We got a CDN_SHAREVIOLATION notification and want to ignore the second CDN_FILEOK notification if (this.okNotificationCount == 0) { this.okNotificationCount = 1; // This one is the first and is all right. } else { // This is the second CDN_FILEOK, so we want to ignore it. this.ignoreSecondFileOkNotification = false; UnsafeNativeMethods.SetWindowLong(new HandleRef(null, hWnd), 0, new HandleRef(null, NativeMethods.InvalidIntPtr)); return(NativeMethods.InvalidIntPtr); } } if (!DoFileOk(notify.lpOFN)) { UnsafeNativeMethods.SetWindowLong(new HandleRef(null, hWnd), 0, new HandleRef(null, NativeMethods.InvalidIntPtr)); return(NativeMethods.InvalidIntPtr); } break; } } catch { if (dialogHWnd != IntPtr.Zero) { UnsafeNativeMethods.EndDialog(new HandleRef(this, dialogHWnd), IntPtr.Zero); } throw; } } return(IntPtr.Zero); }