65.9K
CodeProject 正在变化。 阅读更多。
Home

OneNote 式屏幕截图实用程序 - 带预览和自动保存选项

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.45/5 (11投票s)

2011 年 7 月 2 日

CPOL

3分钟阅读

viewsIcon

47362

downloadIcon

2646

一个像 OneNote(Office 2010)一样捕获和裁剪屏幕的实用程序。

Preview_Media_updated.png

引言

你们大多数使用“OneNote”的人可能都体验过 Office 2010 套件中新增的屏幕捕捉功能。与传统的打印屏幕功能不同,此工具提供了一个选项来冻结屏幕并在活动桌面上裁剪图像。

在为我们的应用程序创建类似 Office 2010 的 Ribbon 时,我发现这真的很有帮助,可以获得 Office 2010 视觉效果的细微细节。这是一个实用程序,可让您获得相同的屏幕捕捉和裁剪体验。

背景

这是它的工作原理

  • 主应用程序在后台运行,并监听热键(Win 键 + S)来捕捉屏幕。
  • 一旦主应用程序收到 WM_HOTKEY 消息,主应用程序就会捕获桌面并将其传递到 adorner 窗口。
  • adorner 窗口在所有其他窗口的顶部呈现不透明的图像,供您用鼠标裁剪。
  • 裁剪后的图像随后被放入剪贴板,就完成了!

Using the Code

监听热键

热键是用户可以激活此应用程序的选项。 为了使此工作正常进行,此应用程序使用本机 pinvoke 来注册和注销热键。

RegisterHotKey

此函数需要一个调用窗口的句柄,当按下键组合时,WM_HOTKEY 消息将发布到该窗口,以及一个 ID 作为对热键的引用(此值存在一个范围,请参阅文档的“备注”部分),以及一个修饰符值,指定与 key 参数一起注册的修饰键。

Win 键与“S”键一起用作此应用程序的热键,该函数的代码位于以下代码块中。

// Definition of Native Method.
[DllImport("user32.dll", SetLastError = true)]
private static extern int RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, Keys vk);

//Param : A handle to the window, an id for the hotkey ,id of modifer key and the key.
RegisterHotKey(this.Handle, hotKeyId,/*MOD_WIN*/0x0008, Keys.S);

UnregisterHotKey

取消注册热键相对简单,它需要一个调用窗口的句柄以及注册热键时使用的 ID。

// A handle to the calling window and the id used while registering.
UnregisterHotKey(this.Handle, hotKeyId);

下一个重要的事情是获取桌面窗口的位图,存在一个本机函数 GetDesktopWindow 来获取桌面句柄,您可以使用它将图形上下文复制到位图。 或者,可以使用 Graphics.CopyFromScreen 方法来完成,如下所述,该位图稍后将作为不透明图像投影,从而提供冻结的桌面外观。

public static Bitmap GenerateScreenBitmap()
{
    Rectangle scrBounds = Screen.PrimaryScreen.Bounds;
    Bitmap bmp = new Bitmap(scrBounds.Width, scrBounds.Height);
    Graphics g = Graphics.FromImage(bmp);

    g.CopyFromScreen(Point.Empty, Point.Empty, 
	scrBounds.Size, CopyPixelOperation.SourceCopy);

    bitmapCache = bmp;

    return bmp;
}

生成的位图图像被设置为 adorner 窗口的背景,并且显示该窗口,该 adorner 窗口覆盖其 OnPaint 方法以使用 alpha 混合填充该区域,以提供不透明的外观。 adorner 处理鼠标事件以确定裁剪区域。 dragStart dragStop 确定裁剪图像的左上角和右下角点。

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    Region clip = e.Graphics.Clip;

    if (mousePressed && dragStart!= Point.Empty && dragStart != dragStop)
    {
        Rectangle rect = Rectangle.FromLTRB
		(dragStart.X, dragStart.Y, dragStop.X, dragStop.Y);

        using (Pen pen = new Pen(Color.Black))
        {
            e.Graphics.DrawRectangle(pen, Rectangle.Inflate(rect,-1,-1));
        }

        // Excludes the cropped region and paints the remaining surface.
        e.Graphics.SetClip(rect, CombineMode.Exclude);
    }

    using (Brush brush = new SolidBrush(Color.FromArgb(210,Color.WhiteSmoke)))
    {
        e.Graphics.FillRectangle(brush, this.ClientRectangle);
    }

    e.Graphics.SetClip(clip, CombineMode.Replace);
}

当按下鼠标按钮或按下键时,adorner 将被关闭,并且 dragStartdragStop 点将被传递到主窗口,主窗口将目标裁剪图像复制到剪贴板。

Rectangle rect = Rectangle.FromLTRB(adornerWindow.DragStart.X, 
	adornerWindow.DragStart.Y, adornerWindow.DragStop.X, adornerWindow.DragStop.Y);

Bitmap result = new Bitmap(rect.Width, rect.Height);
Graphics g = Graphics.FromImage(result);

g.DrawImage(bitmapCache,new Rectangle(Point.Empty,result.Size), rect, GraphicsUnit.Pixel);

Clipboard.SetImage(result);

就这样,图像现在已复制到剪贴板,您可以将其粘贴到任何需要的地方。

关注点

此实用程序提供了一个选项,可以在 Windows 启动时启动此应用程序,这是您可以实现它的方法,它只需要将应用程序启动路径和应用程序名称放置在以下位置的注册表项中

string RegKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";

RegistryKey startUpKey = Registry.CurrentUser.OpenSubKey(RegKey, true);
                
ToolStripMenuItem menuItem = (sender as ToolStripMenuItem);
menuItem.Checked = !menuItem.Checked;

if (menuItem.Checked)
    startUpKey.SetValue(APP_NAME, Application.ExecutablePath);
else
    startUpKey.DeleteValue(APP_NAME, false);

希望这对您的日常工作有所帮助。 请留下您宝贵的意见和建议。 祝您编码愉快!

© . All rights reserved.