C# 线程间不能调用剪切板的解决方法

在做外部程序窗口截图时候,

用C#  g.CopyFromScreen(new Point(x, y), new Point(0, 0), bmp.Size);方法

或WinAPI 

        [DllImport("user32.dll")]
        private static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, UInt32 nFlags);
方法无法截取到屏幕图片。特别是动态窗口,如:播放电影的窗口;

只能用快捷键 PrintScreen 或 Alt PrintScreen 屏幕截图到剪切板中实现截图;

 

 [DllImport("user32.dll" ,EntryPoint = "keybd_event")]
        static extern void Keybd_event(byte bVk, byte bScan, uint dwFlags,UIntPtr dwExtraInfo);//该函数合成一次击键事件

const int KEYEVENTF_KEYUP = 0x2;//若指定该值,该键将被释放;若未指定该值,该键将被按下

        public void Keydown(Keys k)
        {//按下
            Keybd_event((byte)k, 0, 0, UIntPtr.Zero);
        }

        public void Keyup(Keys k)
        {//释放
            Keybd_event((byte)k, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
        }


        void Print_Screen()
        {//模拟PrintScreen
            Keydown(Keys.PrintScreen);
            Application.DoEvents();
            Keyup(Keys.PrintScreen);
            Application.DoEvents();
        }


        void Alt_PrintScreen()
        {//模拟Alt+PrintScreen
            Keydown(Keys.Menu);
            Keydown(Keys.PrintScreen);
            Application.DoEvents();
            Keyup(Keys.PrintScreen);
            Keyup(Keys.Menu);
            Application.DoEvents();

        }

        /// 
        /// 全屏打印
        /// 
        /// 
        public Image PrintAllScreen()
        {
            //打印全屏
            Print_Screen();
            Image result = null;
            if (Clipboard.ContainsImage())
            {//功能提取或替换Windows系统剪贴板的图片
                result = Clipboard.GetImage();
            }
            return result;
        }


        /// 
        /// 窗口打印
        /// 
        /// 
        public Image PrintWindowScreen()
        {
            //打印全屏
            Alt_PrintScreen();
            Image result = null;
            if (Clipboard.ContainsImage())
            {//功能提取或替换Windows系统剪贴板的图片
                result = Clipboard.GetImage();
            }
            return result;
        }


但是,上述代码使用线程调用时,就无法读取剪切板中的内容。下面方法可以解决这个问题;

第一步:

1

2

3

4

5

6

7

8

9

public void btnAutoFocus_Click(object sender,EventArgs e)

{

    Thread myThread = new Thread(msc.AutoFocusArithmetic);

    //注意,一般启动一个线程的时候没有这句话,但是要操作剪切板的话这句话是必需要加上的,

    //因为剪切板只能在单线程单元中访问

    //这里的STA就是指单线程单元

    myThread .SetApartmentState(ApartmentState.STA);

    myThread .Start();

}

第二步:还需要将Program启动类中

1

2

3

4

5

6

7

8

9

10

11

12

13

14

static class Program

{

    ///

    /// 应用程序的主入口点。

    ///

    [STAThread] //这句话保留,如果要在主线程中访问剪切板,这句式必须要的

    //如果要在子线程中访问剪切板,这个应该可以不要,但是默认是有的

    static void Main()

    {

        Application.EnableVisualStyles();

        Application.SetCompatibleTextRenderingDefault(false);

        Application.Run(new MainForm());

        }

}

第三步:这个是读取剪切板数据

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

private Image GetCaptureImage()

{

    IDataObject iData = Clipboard.GetDataObject();

    Image img = null;

    if (iData != null)

    {

    if (iData.GetDataPresent(DataFormats.Bitmap))

    {

        img = (Image)iData.GetData(DataFormats.Bitmap);

    }

    else if (iData.GetDataPresent(DataFormats.Dib))

    {

        img = (Image)iData.GetData(DataFormats.Dib);

    }

}

    return img;

}

 

你可能感兴趣的:(C# 线程间不能调用剪切板的解决方法)