欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

通過C#編寫一個簡易的Windows截屏增強工具

 更新時間:2022年05月11日 14:54:32   作者:he55  
在使用?Windows?系統(tǒng)的截屏快捷鍵?PrintScreen?截屏時,如果需要把截屏保存到文件,需要先粘貼到畫圖工具然后另存為文件。所以本文用C#編寫了一個簡易的Windows截屏增強工具,需要的可以參考一下

半年前我開源了 DreamScene2 一個小而快并且功能強大的 Windows 動態(tài)桌面軟件。有很多的人喜歡,這使我有了繼續(xù)做開源的信心。這是我的第二個開源作品 ScreenshotEx 一個簡單易用的 Windows 截屏增強工具。

前言

在使用 Windows 系統(tǒng)的截屏快捷鍵 PrintScreen 截屏時,如果需要把截屏保存到文件,需要先粘貼到畫圖工具然后另存為文件。以前我還沒有覺得很麻煩,后來使用了 macOS 系統(tǒng)的截屏工具,我才知道原來一個小小的截屏工具也可以這么簡單易用。于是參考 macOS 系統(tǒng)的截屏工具做了一個 Windows 版的。

功能

自動保存截屏到桌面

img

點擊截屏預覽可以編輯截屏

img

實現(xiàn)原理

如果想在按下系統(tǒng)的截屏快捷鍵后做一些事情,能想到的方法應該就是如何監(jiān)聽鍵盤事件。WIN32 API 提供的 SetWindowsHookExA 鉤子函數(shù)剛好可以實現(xiàn)這個需求,idHook 參數(shù)設置成 WH_KEYBOARD_LL 時是低等級鍵盤鉤子可以捕獲鍵盤消息。

SetWindowsHookExA 函數(shù)定義

HHOOK SetWindowsHookExA(
  [in] int       idHook,    // 鉤子類型
  [in] HOOKPROC  lpfn,      // 鉤子處理函數(shù)
  [in] HINSTANCE hmod,      // 模塊句柄
  [in] DWORD     dwThreadId // 線程Id
);

鍵盤處理函數(shù)定義

LRESULT CALLBACK LowLevelKeyboardProc(
  _In_?int ???nCode,
  _In_?WPARAM wParam, // 鍵盤消息
  _In_?LPARAM lParam // KBDLLHOOKSTRUCT 結(jié)構(gòu)體指針
);

代碼

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);

注冊鍵盤鉤子

需要注意:因為 SetWindowsHookEx 是非托管函數(shù)第二個參數(shù)是個委托類型,GC 不會記錄非托管函數(shù)對 .NET 對象的引用。如果用臨時變量保存委托出作用域就會被 GC 釋放,當 SetWindowsHookEx 去調(diào)用已經(jīng)被釋放的委托就會報錯。

SetWindowsHookEx 函數(shù)第一個參數(shù)傳 WH_KEYBOARD_LL 低等級鍵盤鉤子、第二個參數(shù)傳鍵盤消息處理函數(shù)的委托、第三個參數(shù)使用 GetModuleHandle 函數(shù)獲取模塊句柄、第四個參數(shù)傳 0。

HookProc _hookProc;
IntPtr _hhook;

void StartHook() 
{
    _hookProc = new HookProc(LowLevelKeyboardProc); // 使用成員變量保存委托
    _hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _hookProc, GetModuleHandle(null), 0); // 注冊鍵盤鉤子,保存返回值卸載鉤子時用到。GetModuleHandle(null) 獲取當前模塊句柄
}

鍵盤消息處理函數(shù)

在鍵盤消息處理函數(shù)里面捕獲 PrintScreen 按鍵消息,然后顯示預覽和保存圖片邏輯

IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam)
{
    if (nCode == HC_ACTION)
    {
        if (lParam.vkCode == VK_SNAPSHOT) // 捕獲 PrintScreen 按鍵消息
        {
            if ((int)wParam == WM_KEYUP || (int)wParam == WM_SYSKEYUP) // 按鍵釋放時保存圖片
                SaveImage();
            else
                _previewWindow.SetHide();
        }
    }
    return CallNextHookEx(_hhook, nCode, wParam, ref lParam);
}

保存圖片

從系統(tǒng)剪貼板獲取圖片

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);
    }
}

以上就是通過C#編寫一個簡易的Windows截屏增強工具的詳細內(nèi)容,更多關于C#截屏增強工具的資料請關注腳本之家其它相關文章!

相關文章

  • C# 實現(xiàn)把double 存成兩位精度小數(shù)

    C# 實現(xiàn)把double 存成兩位精度小數(shù)

    這篇文章主要介紹了C# 實現(xiàn)把double 存成兩位精度小數(shù),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • C#實現(xiàn)將數(shù)組內(nèi)元素打亂順序的方法

    C#實現(xiàn)將數(shù)組內(nèi)元素打亂順序的方法

    這篇文章主要介紹了C#實現(xiàn)將數(shù)組內(nèi)元素打亂順序的方法,涉及C#數(shù)組遍歷及隨機數(shù)操作的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • c# 獲取照片的經(jīng)緯度和時間的示例代碼

    c# 獲取照片的經(jīng)緯度和時間的示例代碼

    這篇文章主要介紹了c# 獲取照片的經(jīng)緯度和時間的示例代碼,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2020-11-11
  • C#向word文檔插入新段落及隱藏段落的方法

    C#向word文檔插入新段落及隱藏段落的方法

    這篇文章主要為大家詳細介紹了C#如何向word文檔插入一個新段落及隱藏段落 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 詳析C#的協(xié)變和逆變

    詳析C#的協(xié)變和逆變

    這篇文章主要介紹了詳析C#的協(xié)變和逆變,在引用類型系統(tǒng)時,協(xié)變、逆變和不變性具有如下定義。?這些示例假定一個名為?Base?的基類和一個名為?Derived的派生類,更多內(nèi)容請需要的小伙伴參考下面文章內(nèi)容
    2022-01-01
  • C# 獲取XML文件內(nèi)容的多種方式總結(jié)

    C# 獲取XML文件內(nèi)容的多種方式總結(jié)

    這篇文章主要介紹了C# 獲取XML文件內(nèi)容的多種方式總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • LINQ(語言集成查詢)使用案例

    LINQ(語言集成查詢)使用案例

    這篇文章介紹了LINQ(語言集成查詢)的使用案例,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • C#實現(xiàn)數(shù)獨解法

    C#實現(xiàn)數(shù)獨解法

    這篇文章介紹了C#實現(xiàn)數(shù)獨解法的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • C# using的本質(zhì)及使用詳解

    C# using的本質(zhì)及使用詳解

    這篇文章主要為大家介紹了C# using的本質(zhì)及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • .NET中保證線程安全的高級方法Interlocked類使用介紹

    .NET中保證線程安全的高級方法Interlocked類使用介紹

    這篇文章主要介紹了.NET中保證線程安全的高級方法Interlocked類使用介紹,Interlocked類可以為為多個線程共享的變量提供原子操作,需要的朋友可以參考下
    2014-07-07

最新評論