Я использую код из этого ответа для записи нескольких секунд записи всего экрана, и все работает отлично - я получаю GIF с записью экрана, сделанной из PNG. Но когда я добавляю Application.Run();
в Main()
метод, чтобы и моя ловушка KeyHook работала как положено, запись экрана перестала работать ... Есть идеи, почему это происходит?
Application.Run();
- это одно из пространства имен System. Windows .Forms.
Код из класса методов Main:
public static void Main(string[] args)
{
ScreenRecorder.Start();
// need for LowLevelKeyboardListener
Application.Run();
int n = 5; //seconds of capturing
//DispatcherTimer dispacherTimer = new DispatcherTimer();
Timer timer = new Timer(n * 1000);
timer.Interval = n * 1000;
timer.Elapsed += _timer_Tick;
timer.AutoReset = false;
timer.Enabled = true;
//timer.Start();
_listener = new LowLevelKeyboardListener();
_listener.OnKeyPressed += _listener_OnKeyPressed;
_listener.HookKeyboard();
Console.ReadKey();
_listener.UnHookKeyboard();
}
public static void _listener_OnKeyPressed(object sender, KeyPressedArgs e)
{
Console.WriteLine(e.KeyPressed.ToString());
Console.Beep();
}
public static void _timer_Tick(object sender, EventArgs e)
{
ScreenRecorder.Stop();
ScreenRecorder.Save(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\video.gif");
ScreenRecorder.ClearRecording();
Console.WriteLine("recording saved");
}
Код из ScreenRecorder:
public class ScreenRecorder
{
private static string tempDir = Path.GetTempPath() + "/snapshot/";
private static System.Threading.Thread snap = new System.Threading.Thread(Snapshot);
private static System.Drawing.Rectangle _Bounds = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
public static System.Drawing.Rectangle Bounds
{
get { return _Bounds; }
set { _Bounds = value; }
}
private static void Snapshot()
{
if (!Directory.Exists(tempDir))
Directory.CreateDirectory(tempDir);
int Co = 0;
do
{
Co += 1;
System.Threading.Thread.Sleep(50);
System.Drawing.Bitmap X = new System.Drawing.Bitmap(_Bounds.Width, _Bounds.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using(System.Drawing.Graphics G = System.Drawing.Graphics.FromImage(X)) {
G.CopyFromScreen(_Bounds.Location, new System.Drawing.Point(), _Bounds.Size);
System.Drawing.Rectangle CurBounds = new System.Drawing.Rectangle(System.Drawing.Point.Subtract(System.Windows.Forms.Cursor.Position,Bounds.Size), System.Windows.Forms.Cursor.Current.Size);
System.Windows.Forms.Cursors.Default.Draw(G, CurBounds);
}
System.IO.FileStream FS = new System.IO.FileStream(tempDir + FormatString(Co.ToString(), 5, '0') + ".png", System.IO.FileMode.OpenOrCreate);
X.Save(FS, System.Drawing.Imaging.ImageFormat.Png);
X.Dispose();
FS.Close();
} while (true);
}
public static void ClearRecording()
{
if (Directory.Exists(tempDir))
Directory.Delete(tempDir, true);
Directory.CreateDirectory(tempDir);
}
public static void Save(string Output)
{
System.Windows.Media.Imaging.GifBitmapEncoder G = new System.Windows.Media.Imaging.GifBitmapEncoder();
List<System.IO.FileStream> X = new List<System.IO.FileStream>();
foreach (string Fi in Directory.GetFiles(tempDir, "*.png", SearchOption.TopDirectoryOnly))
{
System.IO.FileStream TempStream = new System.IO.FileStream(Fi, System.IO.FileMode.Open);
System.Windows.Media.Imaging.BitmapFrame Frame = System.Windows.Media.Imaging.BitmapFrame.Create(TempStream);
X.Add(TempStream);
G.Frames.Add(Frame);
}
System.IO.FileStream FS = new System.IO.FileStream(Output, System.IO.FileMode.OpenOrCreate);
G.Save(FS);
FS.Close();
foreach (System.IO.FileStream St in X)
{
St.Close();
}
}
public static void Start()
{
snap = new System.Threading.Thread(Snapshot);
snap.Start();
}
public static void Stop()
{
snap.Abort();
}
private static string FormatString(string S, int places, char character)
{
if (S.Length >= places)
return S;
for (int X = S.Length; X <= places; X++)
{
S = character + S;
}
return S;
}
}
Код для KeyboardListener:
public class LowLevelKeyboardListener
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private const int WM_SYSKEYDOWN = 0x0104;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
public event EventHandler<KeyPressedArgs> OnKeyPressed;
private LowLevelKeyboardProc _proc;
private IntPtr _hookID = IntPtr.Zero;
public LowLevelKeyboardListener()
{
//_setHookReference = SetHook;
_proc = HookCallback;
}
public void HookKeyboard()
{
_hookID = SetHook(_proc);
}
public void UnHookKeyboard()
{
UnhookWindowsHookEx(_hookID);
}
private IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
IntPtr hook = SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
//SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle("user32"), 0);
if (hook == IntPtr.Zero)
{
throw new Win32Exception();
}
return hook;
}
}
public IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (OnKeyPressed != null)
OnKeyPressed(this, new KeyPressedArgs(KeyInterop.KeyFromVirtualKey(vkCode)));
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
}
Обычно оба функциональные возможности (перехват клавиш и запись экрана) работают правильно, но не вместе, когда Application.Run()
регулируется.