0

在 C# winform 应用程序中。我正在编写一个剪贴板日志管理器,它将文本记录到日志文件中,(每次按下 Ctrl+c/x 时,复制/剪切的文本都会附加到文件中)我也对图像做了同样的事情,也就是说,如果你按“prtScreen”,您拍摄的屏幕截图也会转到一个文件夹。

我通过使用计时器来做到这一点,在里面我有一些“看起来”像这样的东西:

if (Clipboard.ContainsImage())
{
  if (IsClipboardUpdated())
  {
    LogData();
    UpdateLastClipboardData();
  }
}

其余方法如下所示:

public void UpdateLastClipboardData()
{
  // ... other updates
  LastClipboardImage = Clipboard.GetImage();
}
// This is how I determine if there's a new image in the clipboard...
public bool IsClipboardUpdated()
{
  return (LastClipboardImage != Clipboard.GetImage());
}
public void LogData()
{
  Clipboard.GetImage().Save(ImagesLogFolder + "\\Image" + now_hours + "_" + now_mins + "_" + now_secs + ".jpg");  
}

问题是:在更新方法中,“LastClipboardImage != Clipboard.GetImage()”总是返回 true!

我什至在更新方法中做了以下事情:

Image img1 = Clipboard.GetImage();
Image img2 = Clipboard.GetImage();
Image img3 = img2;
bool b1 = img1 == img2; // this returned false. WHY??
bool b2 = img3 == img2; // this returned true. Makes sense.

请帮忙,比较不起作用...为什么?

4

3 回答 3

1

一个小测试。对同一张图片调用两次 GetImage 方法

void Main()
{
    Image bmp1 = Clipboard.GetImage();
    Image bmp2 = Clipboard.GetImage();

    if(bmp1 != null && bmp1 == bmp2)
        Console.WriteLine("True");
    else
        Console.WriteLine("False");
}

它总是返回假。所以每次你调用 Clipboard.GetImage() 你都会得到一个不同的图像实例,因此你无法比较然后使用一个简单的== operator

您正在比较 Image 对象的两个不同实例,当然它们并不相同。

如果您真的想将图像与像素级别进行比较,则需要像这样更具侵入性(且性能要求更高的方法)

bool ImagesAreDifferent(Image img1, Image img2)
{
    Bitmap bmp1 = new Bitmap(img1);
    Bitmap bmp2 = new Bitmap(img2);

    bool different = false;
    if (bmp1.Width == bmp2.Width && bmp1.Height == bmp2.Height)
    {
        for (int i = 0; i < bmp1.Width; i++)
        {
            for (int j = 0; j < bmp1.Height; j++)
            {
                Color col1 = bmp1.GetPixel(i, j);
                Color col2 = bmp2.GetPixel(i, j);
                if (col1 != col2)
                {
                    i = bmp1.Width + 1;
                    different = true;
                    break;
                }
            }
        }
    }    
    return different;
}

请注意这是如何可能的,因为 Color 结构定义了一个Equality 运算符来检查颜色 RGB 值在两种颜色之间是否相同

于 2012-12-08T17:15:52.350 回答
0

Image检查与 的相等性Object.equals,它测试与引用类型的引用相等性,而不是语义相等性。这就是为什么img2 == img3是,因为您之前已将' 引用true复制到. 但是,对于和,您调用which 构造了一个新的图像对象。img2img3img1img2Clipboard.GetImage

如果您真的想测试两个图像对象是否包含相同的数据,您将需要编写自己的方法 - 如果您不想子类化,可能是扩展方法Image

public static class ImageExtensions
{
    public static bool MyEquals(this Image x, Image y)
    {
        // compute and return your definition of equality here
    }
}

请注意,==操作员不会自动调用此方法,您必须使用 . 检查是否相等Image.MyEquals

于 2012-12-08T17:24:20.343 回答
0

我认为您可以更改程序逻辑来克服这个问题,而不是比较图像。如何捕获添加到剪贴板的新项目的事件并写入日志?

您可以从以下链接尝试代码示例代码

http://www.codeproject.com/Tips/467361/Using-Clipboard-Csharp-4-0-Wrapper-inside

// Use the "ClipboardManager" to manage in a more comprehensive the clipboard
// I assume that "this" is a Form
ClipboardManager manager = new ClipboardManager(this);
// Use "All" to handle all kinds of objects from the clipboard
// otherwise use "Files", "Image" or "Text"
manager.Type = ClipboardManager.CheckType.All;
// Use events to manage the objects in the clipboard
manager.OnNewFilesFound += (sender, eventArg) => 
{
    foreach (String item in eventArg)
    {
        Console.WriteLine("New file found in clipboard : {0}", item);
    }
};
manager.OnNewImageFound += (sender, eventArg) =>
{
    Console.WriteLine("New image found in clipboard -> Width: {0} , Height: {1}", 
                      eventArg.Width, eventArg.Height);
};
manager.OnNewTextFound += (sender, eventArg) =>
{
    Console.WriteLine("New text found in clipboard : {0}", eventArg);
};
// Use the method "StartChecking" to start capturing objects in the clipboard
manager.StartChecking();
// Close the capturing
manager.Dispose();
于 2012-12-08T17:38:59.843 回答