C# 编写 Windows 截屏增强工具

科技资讯 投稿 57900 0 评论

C# 编写 Windows 截屏增强工具

DreamScene2 一个小而快并且功能强大的 Windows 动态桌面软件。有很多的人喜欢,这使我有了继续做开源的信心。这是我的第二个开源作品 ScreenshotEx 一个简单易用的 Windows 截屏增强工具。

https://github.com/he55/ScreenshotEx

功能

  • 自动保存截屏到桌面

实现原理

SetWindowsHookExA 钩子函数刚好可以实现这个需求,参数设置成  时是低等级键盘钩子可以捕获键盘消息。

HHOOK SetWindowsHookExA(
  [in] int       idHook,    // 钩子类型
  [in] HOOKPROC  lpfn,      // 钩子处理函数
  [in] HINSTANCE hmod,      // 模块句柄
  [in] DWORD     dwThreadId // 线程Id
;

键盘处理函数定义

LRESULT CALLBACK LowLevelKeyboardProc(
  _In_ int    nCode,
  _In_ WPARAM wParam, // 键盘消息
  _In_ LPARAM lParam // KBDLLHOOKSTRUCT 结构体指针
;

代码

C# PInvoke 定义

const int HC_ACTION = 0;
const int WH_KEYBOARD_LL = 13;
const int WM_KEYUP = 0x0101;
const int WM_SYSKEYUP = 0x0105;
const int VK_SNAPSHOT = 0x2C;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto]
public struct KBDLLHOOKSTRUCT
{
    public uint vkCode;
    public uint scanCode;
    public uint flags;
    public uint time;
    public UIntPtr dwExtraInfo;
}

[UnmanagedFunctionPointer(CallingConvention.Winapi]
public delegate IntPtr HookProc(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam;

[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hmod, int dwThreadId;

[DllImport("User32.dll", SetLastError = true, ExactSpelling = true]
[return: MarshalAs(UnmanagedType.Bool]
public static extern bool UnhookWindowsHookEx(IntPtr hhk;

[DllImport("User32.dll", SetLastError = false, ExactSpelling = true]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam;

[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto]
public static extern IntPtr GetModuleHandle([Optional] string lpModuleName;

注册键盘钩子

函数第一个参数传  低等级键盘钩子、第二个参数传键盘消息处理函数的委托、第三个参数使用  函数获取模块句柄、第四个参数传 0。

HookProc _hookProc;
IntPtr _hhook;

void StartHook( 
{
    _hookProc = new HookProc(LowLevelKeyboardProc; // 使用成员变量保存委托
    _hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _hookProc, GetModuleHandle(null, 0; // 注册键盘钩子,保存返回值卸载钩子时用到。GetModuleHandle(null 获取当前模块句柄
}

键盘消息处理函数

IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam
{
    if (nCode == HC_ACTION
    {
        if (lParam.vkCode == VK_SNAPSHOT // 捕获 PrintScreen 按键消息
        {
            if ((intwParam == WM_KEYUP || (intwParam == WM_SYSKEYUP // 按键释放时保存图片
                SaveImage(;
            else
                _previewWindow.SetHide(;
        }
    }
    return CallNextHookEx(_hhook, nCode, wParam, ref lParam;
}

保存图片

void SaveImage(
{
    if (Clipboard.ContainsImage(
    {
        if (!Directory.Exists(_settings.SavePath
            Directory.CreateDirectory(_settings.SavePath;

        string ext = "png";
        ImageFormat imageFormat = ImageFormat.Png;
        switch (_settings.SaveExtension
        {
            case 0:
                imageFormat = ImageFormat.Png;
                ext = "png";
                break;
            case 1:
                imageFormat = ImageFormat.Jpeg;
                ext = "jpg";
                break;
            case 2:
                imageFormat = ImageFormat.Bmp;
                ext = "bmp";
                break;
        }

        if (_settings.SaveName == 0
        {
            string name = DateTime.Now.ToString("yyyy-MM-dd HH.mm.ss";
            _saveFilePath = Path.Combine(_settings.SavePath, $"{PrefixName} {name}.{ext}";
        }
        else
        {
            do
            {
                _saveFilePath = Path.Combine(_settings.SavePath, $"{PrefixName} {_nameIndex}.{ext}";
                _nameIndex++;
            } while (File.Exists(_saveFilePath;
        }

        Image image = Clipboard.GetImage(;
        image.Save(_saveFilePath, imageFormat;

        if (_settings.IsPlaySound
            _soundPlayer.Play(;

        if (_settings.IsShowPreview
            _previewWindow.SetImage(_saveFilePath;
    }
}

完整代码 https://github.com/he55/ScreenshotEx

编程笔记 » C# 编写 Windows 截屏增强工具

赞同 (88) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽