2

我用 C# 编写了一个监视剪贴板的小程序。当某个字符串进入剪贴板时,必须使用 Process.Start 打开程序(取决于字符串)。一切正常,但有时应用程序被打开两次。我不知道为什么会这样。

namespace ClipboardMonitor {
    public class Form1 : System.Windows.Forms.Form {
        [DllImport("User32.dll")]
        protected static extern int SetClipboardViewer(int hWndNewViewer);
        [DllImport("User32.dll", CharSet=CharSet.Auto)]
        public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
        [DllImport("user32.dll", CharSet=CharSet.Auto)]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();
        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        const int SW_HIDE = 0;
        const int SW_SHOW = 5;
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        IntPtr nextClipboardViewer;
        private System.ComponentModel.Container components = null;

        public Form1() {
            InitializeComponent();
            nextClipboardViewer = (IntPtr)SetClipboardViewer((int) this.Handle);
            var handle = GetConsoleWindow();
            ShowWindow(handle, SW_HIDE);
        }
        protected override void Dispose( bool disposing ) {
            ChangeClipboardChain(this.Handle, nextClipboardViewer);
            if( disposing ) {
                if (components != null) {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }
        private void InitializeComponent() {
            this.WindowState = FormWindowState.Minimized;
            this.ShowInTaskbar = false;
            this.Name = "Form1";
        }

        [STAThread]
        static void Main()  {
            Application.Run(new Form1());
        }

        protected override void WndProc(ref System.Windows.Forms.Message m) {
            const int WM_DRAWCLIPBOARD = 0x308;
            const int WM_CHANGECBCHAIN = 0x030D;

            switch(m.Msg) {
                case WM_DRAWCLIPBOARD:
                    DisplayClipboardData();
                    SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    break;
                case WM_CHANGECBCHAIN:
                    if (m.WParam == nextClipboardViewer)
                        nextClipboardViewer = m.LParam;
                    else
                        SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }

        void DisplayClipboardData() {
            Thread.Sleep(500);
            try {
                IDataObject iData = new DataObject();  
                iData = Clipboard.GetDataObject();
                 if (iData.GetDataPresent(DataFormats.Text)) {
                    string path = iData.GetData(DataFormats.Text).ToString();
                    string[] words = path.Split('_');
                    if (words[0] == "startLO") {
                            ProcessStartInfo info = new ProcessStartInfo(words[1]);
                            Process p = Process.Start(info);
                    }
                } else {
                    // We doen niets.
                }
            }
            catch(Exception e) {
                MessageBox.Show(e.ToString());
            }
        }
    }
4

1 回答 1

0

一种解释是快速连续发生多个剪贴板事件。这是相当普遍的。您可以通过“解决时间”延迟来防御这种情况。即不是立即做出反应,而是设置一个计时器或创建一个线程来“在一段时间内”处理它。随着更多事件的到来,请继续推迟结算时间。当结算时间最终到期时,允许计时器或线程实际运行您的程序。

于 2012-12-04T15:31:42.840 回答