(Short Screen-Cast explaining the problem)
我正在制作剪贴板程序,可让您查看剪贴板中的内容。
它似乎可以在飞行中进行精细复制。
问题是我希望能够在剪贴板中返回之前的img / txt并使用它 - 当我使用复选标记按钮时。
它有效,唯一的问题是它将它复制两次到我使用的图像列表/列表框中。当我初始化列表框/图片框时也会发生这种情况。
以下是代码:
namespace Clipboard_Wizard
{
public partial class FormMain : Form
{
//register the program in the clipboard viewer chain
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
private const int WM_DRAWCLIPBOARD = 0x0308; // WM_DRAWCLIPBOARD message
private IntPtr _clipboardViewerNext; // Our variable that will hold the value to identify the next window in the clipboard viewer chain
private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
ChangeClipboardChain(this.Handle, _clipboardViewerNext); // Removes our from the chain of clipboard viewers when the form closes.
}
List<Image> img = new List<Image>();
int ImgCount = 0;
int ImgIndex = -1;
Image tmp;
public FormMain()
{
InitializeComponent();
_clipboardViewerNext = SetClipboardViewer(this.Handle); // Adds our form to the chain of clipboard viewers.
//set listbox/picturebox to whatever already on clipboard
if (Clipboard.ContainsImage())
{
tmp = Clipboard.GetImage();
pictureBox1.Image = tmp;
img.Add(tmp);
ImgCount++;
ImgIndex++;
btnSlctImg.Enabled = true;
label3.Text = "Image 1 / 1";
}
else if (Clipboard.ContainsText())
{
listBox1.Items.Add(Clipboard.GetText());
}
}
// clears everything from the form and the clipboard
private void btnClear_Click(object sender, EventArgs e)
{
Clipboard.Clear();
listBox1.Items.Clear();
img.Clear();
pictureBox1.Image = null;
ImgCount = 0;
ImgIndex = -1;
btnSlctImg.Enabled = false;
}
private void btnUpdate_Click(object sender, EventArgs e)
{
/*if (Clipboard.ContainsImage())
{
tmp = Clipboard.GetImage();
pictureBox1.Image = tmp;
img.Add(tmp);
ImgCount++;
ImgIndex = ImgCount - 1;
}
else if (Clipboard.ContainsText())
{
listBox1.Items.Add(Clipboard.GetText());
listBox1.TopIndex = listBox1.Items.Count - 1;
}*/
}
private void btnUp_Click(object sender, EventArgs e)
{
if(ImgIndex == -1)
{
MessageBox.Show("No image.");
}
else if (ImgIndex < ImgCount - 1)
{
ImgIndex++;
pictureBox1.Image = img[ImgIndex];
label3.Text = "Image " + (ImgIndex + 1).ToString() + " / " + ImgCount.ToString() ;
}
else
{
MessageBox.Show("This is the last image.");
}
}
private void btnDown_Click(object sender, EventArgs e)
{
if(ImgIndex == -1)
{
MessageBox.Show("No image.");
}
else if (ImgIndex > 0)
{
ImgIndex--;
pictureBox1.Image = img[ImgIndex];
label3.Text = "Image " + (ImgIndex + 1).ToString() + " / " + ImgCount.ToString();
}
else
{
MessageBox.Show("This is the first image.");
}
}
private void btnDeselect_Click(object sender, EventArgs e)
{
listBox1.SelectedIndex = -1;
}
//sets clipboard to selected txt from listbox
private void btnSlct_Click(object sender, EventArgs e)
{
string slctTxt = listBox1.SelectedItem.ToString();
if (slctTxt != null || slctTxt != "")
{
Clipboard.SetText(slctTxt);
}
}
//sets clipboard to selected image
private void btnSlctImg_Click(object sender, EventArgs e)
{
Image slctImg = pictureBox1.Image;
if (slctImg != null)
{
Clipboard.SetImage(slctImg);
}
}
private void listBox1_SelectedIndexChanged_1(object sender, EventArgs e)
{
if (listBox1.SelectedIndex != -1)
{
btnSlctTxt.Enabled = true;
}
else
{
btnSlctTxt.Enabled = false;
}
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m); // Process the message
if (m.Msg == WM_DRAWCLIPBOARD)
{
//btnUpdate.PerformClick();
IDataObject iData = Clipboard.GetDataObject(); // Clipboard's data
if (iData.GetDataPresent(DataFormats.Text))
{
string text = (string)iData.GetData(DataFormats.Text); // Clipboard text
listBox1.Items.Add(text);
listBox1.TopIndex = listBox1.Items.Count - 1;
}
else if (iData.GetDataPresent(DataFormats.Bitmap))
{
tmp = (Bitmap)iData.GetData(DataFormats.Bitmap); // Clipboard image
pictureBox1.Image = tmp;
img.Add(tmp);
ImgCount++;
ImgIndex = ImgCount - 1;
label3.Text = "Image " + ImgCount.ToString() + " / " + ImgCount.ToString();
btnSlctImg.Enabled = true;
}
}
}
}
}
更新:似乎问题出现在我调用Clipboard.SetImage(...)
或Clipboard.SetText(...)
时 - 它会执行两次。尽管如此,仍然不明白为什么。
答案 0 :(得分:1)
您已定义WndProc
到捕捉对剪贴板的更改,并将内容添加到列表中。
在btnSlctImg_Click
中执行此操作:
if (slctImg != null) { Clipboard.SetImage(slctImg); }
因此,当然剪贴板 已更改,WndProc
会被触发,当前所选图像会再次添加到您拥有的列表中。
为避免这种情况,您可能需要测试列表以查看图像或文本是否已在列表中。对于文本来说,这是微不足道的,但对于图像,这不是简单的。您可能必须创建和存储指纹以确定图像是否已存在于列表中。
Here is a post,其中包含为图像创建MD5哈希的示例。
更简单的技巧将是btnSlctImg_Click
在Clipboard.SetImage
之前设置的标记,并在{{1}中进行测试和清除}}。您仍然可以获得重复项,但前提是该程序的用户外部复制了相同的数据。
答案 1 :(得分:-1)
前段时间我写了一个剪贴板工具并将其发布在CodeProject ClipSpy+
上我认为它可以帮助你做你正在做的事情!