2

クリップボードを監視する短いプログラムを C# で作成しました。特定の文字列がクリップボードに入ると、Process.Start でプログラムを開く必要があります (文字列によって異なります)。すべて正常に動作しますが、アプリケーションが 2 回開かれることがあります。なぜこれが起こっているのかわかりません。

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

1つの説明は、複数のクリップボードイベントが急速に連続して発生しているということです。これはかなり一般的です。「セトリングタイム」の遅延でこれを防ぐことができます。つまり、すぐに反応する代わりに、タイマーを設定するか、「しばらくして」それを処理するスレッドを作成します。より多くのイベントが発生するので、決済時間を延期し続けます。settletimeが最終的に期限切れになると、タイマーまたはスレッドが実際にプログラムを実行できるようになります。

于 2012-12-04T15:31:42.840 に答える