一、背景


 

Smallpdf 网站针对PDF文件提供了非常齐全的功能:PDF 与 Word、PPT、Excel、JPG 的相互转化、PDF 的压缩、编辑、合并、分割、解密、加密等功能,用户无需注册即可免费使用。

但是不注册每小时只能处理有限的PDF,对于我们这种有大量PDF需要压缩的人来说就不太合适啦,所以购买了专业版,其在线版本提供了批量压缩的功能,需要上批量上传等待压缩后再下载(存在批量上传后,浏览器卡死或者无法压缩一直等待,以及压缩成功后无法下载,速度只有几十K),而客户端程序版本又没有批量压缩的功能,只能一篇一篇的打开压缩。

为了解解上述问题,经过考虑,准备利用其客户端的压缩功能来进行批量压缩,虽然时间花得久点,但是在本地不用考虑网络因素这些,至少非常可控,但是是不可能人工一篇一篇来压的,所以这就是这篇文章的由来。


 

二、先看实现后的效果:


 

三、实现原理

  主要的原理就是调用WIN API模拟点击,辅助其它的操作完成整个功能,主要的实现就贴主要的代码了,看注释。

       需要的API

      

        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);


        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);

        [DllImport("user32.dll")]
        public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
        const int WM_CLOSE = 0x0010;
        const int WM_CLICK = 0x00F5;

          enum MouseEventFlag : uint
        {
            Move = 0x0001,
            LeftDown = 0x0002,
            LeftUp = 0x0004,
            RightDown = 0x0008,
            RightUp = 0x0010,
            MiddleDown = 0x0020,
            MiddleUp = 0x0040,
            XDown = 0x0080,
            XUp = 0x0100,
            Wheel = 0x0800,
            VirtualDesk = 0x4000,
            Absolute = 0x8000
        }

        [DllImport("user32.dll")]
        static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo);

        [DllImport("user32.dll")]
        public static extern int SetCursorPos(int x, int y);

        public static void MouseLefClickEvent(int dx, int dy, uint data)
        {
            SetCursorPos(dx, dy);
            mouse_event(MouseEventFlag.LeftDown, dx, dy, data, UIntPtr.Zero);
            mouse_event(MouseEventFlag.LeftUp, dx, dy, data, UIntPtr.Zero);
        }

         核心实现:

           var pdfFile = PdfFiles[Index];
            var pdfName = Path.GetFileName(pdfFile);

            //用smallpdf打开指定PDF
            System.Diagnostics.Process.Start(SMALLPDFEXE, $"\"{pdfFile}\"");

            while (true)
            {
                //加入等待时间,打开PDF需要一定时间
                Thread.Sleep(5000);

                //smallpdf窗体句柄
                IntPtr parentWnd = new IntPtr(0);
                parentWnd = FindWindow(null, pdfName);

                if (!parentWnd.Equals(IntPtr.Zero))
                {
                    //保存窗口句柄
                    IntPtr saveWnd = new IntPtr(0);
                    //保存按钮句柄
                    IntPtr btnSave = new IntPtr(0);

                    while (true)
                    {
                        //将指定的pdf居最上面显示
                        SwitchToThisWindow(parentWnd, true);

                        //获取窗口位置信息,用于计算压缩按钮所在位置
                        RECT rc = new RECT();
                        GetWindowRect(parentWnd, ref rc);

                        //点击压缩按钮
                        MouseFlag.MouseLefClickEvent(rc.Right - 50, rc.Top + 100, 0);

                        Thread.Sleep(2000);

                        saveWnd = FindWindow(null, "Save Document");
                        //当找到保存窗口时点击保存按钮,否则一直循环等待
                        if (!saveWnd.Equals(IntPtr.Zero))
                        {
                            btnSave = FindWindowEx(saveWnd, IntPtr.Zero, "Button", "保存(&S)");
                            if (!btnSave.Equals(IntPtr.Zero))
                            {
                                break;
                            }
                        }
                    }
                    //点击保存按钮
                    SendMessage(btnSave, WM_CLICK, IntPtr.Zero, "0");

                    //保存过程等待
                    bool isCompressed = false;
                    int j = 0, checkCount = 60;
                    while (j < checkCount)
                    {
                        //0001-compressed.pdf
                        string compressPdfName = $"{ Path.GetFileNameWithoutExtension(pdfName)}{COMPRESSED}{Path.GetExtension(pdfFile)}";
                        string compressPdfPath = Path.Combine(PDFDIR, compressPdfName);
                        if (File.Exists(compressPdfPath))
                        {
                            isCompressed = true;
                            break;
                        }
                        Thread.Sleep(1000);
                        j++;
                    }

                    //关闭窗体
                    SendMessage(parentWnd, WM_CLOSE, IntPtr.Zero, "0");

                    //如果超时都还没有压缩文件生成,认为压缩不成功,记录。
                    if (!isCompressed)
                    {
                       ///记录
                    }
                    break;
                }
            }
        }

 

        

 

posted on 2018-08-31 10:15 qwsf01115 阅读() 评论() 编辑 收藏

版权声明:本文为dengxi原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/dengxi/p/9564227.html