画像ボックスに画像を保持するアプリケーションがあります。ctrl+C を押すと、画像がクリップボードにコピーされます。スレッドを使用して、実際のクリップボード操作を実行します。
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Control | Keys.C))
{
clipboardThread = new Thread(copy_to_clipboard);
clipboardThread.SetApartmentState(ApartmentState.STA);
clipboardThread.Start();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void copy_to_clipboard()
{
if (pic_display.Image != null)
{
using (MemoryStream stream = new MemoryStream())
{
clipboardStatus.Text = "Copying image to clipboard...";
pic_display.Image.Save(stream, ImageFormat.Png);
var data = new DataObject("PNG", stream);
Clipboard.Clear();
Clipboard.SetDataObject(data, true);
clipboardStatus.Text = "Copied successfully!";
}
}
}
現在、ctrl+C を繰り返し送信すると (例: キーを押したままにする)、新しいスレッドが生成されます。クリップボード スレッドを再利用するようにコードを変更し、現在データをコピーしているかどうかを教えて、まだ動作中に別のコピー コマンドを実行しようとしないようにするにはどうすればよいですか。
アップデート
今それは動作します
バックグラウンドワーカーを使用するように変更しました
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Control | Keys.C))
{
if (!backgroundWorker1.IsBusy)
backgroundWorker1.RunWorkerAsync();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void copy_to_clipboard()
{
using (var stream = new MemoryStream())
{
clipboardStatus.Text = "Copying image to clipboard...";
pic_display.Invoke((Action)(() => {
if (pic_display.Image != null)
pic_display.Image.Save(stream, ImageFormat.Png);
}));
if (stream.Position == 0) return; // No image was saved
var data = new DataObject("PNG", stream);
BeginInvoke ( (Action) ( ()=> {
Clipboard.Clear();
Clipboard.SetDataObject(data, true);
}
clipboardStatus.Text = "Copied successfully!";
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
copy_to_clipboard();
}
しかし今、例外が発生します
Clipboard.Clear();
言って
Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.