Ejemplo n.º 1
0
        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);
        }