views:

487

answers:

2

I setup catching hotkey on alt+printscreen. It catches perfectly but there is nothing in the buffer - no image. How can I get the image from Clipboard.GetImage() after catching hotkey?

Here is the the code.

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Magic_Screenshot
{
    public enum ModifierKey : uint
    {
        MOD_NULL = 0x0000,
        MOD_ALT = 0x0001,
        MOD_CONTROL = 0x0002,
        MOD_SHIFT = 0x0004,
        MOD_WIN = 0x0008,
    }

    public enum HotKey
    {
        PrintScreen,
        ALT_PrintScreen,
        CONTROL_PrintScreen
    }

    public class HotKeyHelper : IMessageFilter
    {
        const string MSG_REGISTERED = "Горячие клавиши уже зарегистрированы, вызовите UnRegister для отмены регистрации.";
        const string MSG_UNREGISTERED = "Горячие клавиши не зарегистрированы, вызовите Register для регистрации.";
        //Делаем из нашего класса singleton
        public HotKeyHelper()
        {
        }
        //public static readonly HotKeyHelper Instance = new HotKeyHelper();
        public bool isRegistered;
        ushort atom;
        //ushort atom1;
        ModifierKey modifiers;
        Keys keyCode;
        public void Register(ModifierKey modifiers, Keys keyCode)
        {
            //Эти значения нам будут нужны в PreFilterMessage
            this.modifiers = modifiers;
            this.keyCode = keyCode;
            //Не выполнена ли уже регистрация?
            //if (isRegistered)
            //    throw new InvalidOperationException(MSG_REGISTERED);
            //Сохраняем atom, для последующей отмены регистрации
            atom = GlobalAddAtom(Guid.NewGuid().ToString());
            //atom1 = GlobalAddAtom(Guid.NewGuid().ToString());
            if (atom == 0)
                ThrowWin32Exception();
            if (!RegisterHotKey(IntPtr.Zero, atom, modifiers, keyCode))
                ThrowWin32Exception();

            //if (!RegisterHotKey(IntPtr.Zero, atom1, ModifierKey.MOD_CONTROL, Keys.PrintScreen))
            //    ThrowWin32Exception();
            //Добавляем себя в цепочку фильтров сообщений
            Application.AddMessageFilter(this);
            isRegistered = true;
        }
        public void UnRegister()
        {
            //Не отменена ли уже регистрация?
            if (!isRegistered)
                throw new InvalidOperationException(MSG_UNREGISTERED);
            if (!UnregisterHotKey(IntPtr.Zero, atom))
                ThrowWin32Exception();
            GlobalDeleteAtom(atom);
            //Удаляем себя из цепочки фильтров сообщений
            Application.RemoveMessageFilter(this);
            isRegistered = false;
        }
        //Генерирует Win32Exception в ответ на неудачный вызов импортируемой Win32 функции
        void ThrowWin32Exception()
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
        //Событие, инициируемое при обнаружении нажатия HotKeys
        public event HotKeyHelperDelegate HotKeyPressed;

        public bool PreFilterMessage(ref Message m)
        {
            //Проверка на сообщение WM_HOTKEY
            if (m.Msg == WM_HOTKEY &&
                //Проверка на окно
              m.HWnd == IntPtr.Zero &&
                //Проверка virtual key code
                m.LParam.ToInt32() >> 16 == (int)keyCode &&
                //Проверка кнопок модификаторов
                (m.LParam.ToInt32() & 0x0000FFFF) == (int)modifiers &&
                //Проверка на наличие подписчиков сообщения
              HotKeyPressed != null)
            {
                if ((m.LParam.ToInt32() & 0x0000FFFF) == (int)ModifierKey.MOD_CONTROL && (m.LParam.ToInt32() >> 16 == (int)Keys.PrintScreen))
                {
                    HotKeyPressed(this, EventArgs.Empty, HotKey.CONTROL_PrintScreen);
                }
                else if ((m.LParam.ToInt32() & 0x0000FFFF) == (int)ModifierKey.MOD_ALT && (m.LParam.ToInt32() >> 16 == (int)Keys.PrintScreen))
                {
                    HotKeyPressed(this, EventArgs.Empty, HotKey.ALT_PrintScreen);
                }
                else if (m.LParam.ToInt32() >> 16 == (int)Keys.PrintScreen)
                {
                    HotKeyPressed(this, EventArgs.Empty, HotKey.PrintScreen);
                }
            }
            return false;
        }

        //Необходимые Win32 константы и функции
        const string USER32_DLL = "User32.dll";
        const string KERNEL32_DLL = "Kernel32.dll";
        const int WM_HOTKEY = 0x0312;
        [DllImport(USER32_DLL, SetLastError = true)]
        static extern bool RegisterHotKey(IntPtr hWnd, int id, ModifierKey fsModifiers, Keys vk);
        [DllImport(USER32_DLL, SetLastError = true)]
        static extern bool UnregisterHotKey(IntPtr hWnd, int id);
        [DllImport(KERNEL32_DLL, SetLastError = true)]
        static extern ushort GlobalAddAtom(string lpString);
        [DllImport(KERNEL32_DLL)]
        static extern ushort GlobalDeleteAtom(ushort nAtom);
    }
}

Where is the bug?

+1  A: 

The key is caught before being processed, you would have to dispatch the hotkey and let it do its job, then capture the result after the clipboard has been updated via something like the SetClipboardViewer Windows API Call.

Shaun Wilson
A: 

in your event handler add the following code:

captureRect = Screen.PrimaryScreen.Bounds;

// Set the bitmap object to the size of the screen

bmpScreenshot = new Bitmap(captureRect.Width, captureRect.Height, PixelFormat.Format32bppArgb);

// Create a graphics object from the bitmap

gfxScreenshot = Graphics.FromImage(bmpScreenshot);

// Take the screenshot from the upper left corner to the right bottom corner

gfxScreenshot.CopyFromScreen(captureRect.X, captureRect.Y, 0, 0, captureRect.Size, CopyPixelOperation.SourceCopy);

//NOTE: gfxScreenshot is your captured bitmap image, use some simple functions to save or display it

link