gpt4 book ai didi

c# - CallbackOnCollectedDelegate 在 Application.Run(new Form1())

转载 作者:行者123 更新时间:2023-11-30 19:07:22 26 4
gpt4 key购买 nike

我制作了一个非常小的应用程序,可以使用 SlimDX 捕获游戏内的屏幕。(我按下左键点击捕捉)

捕获有效(至少当我点击表单本身时)但是当我点击 firefox 或任何其他应用程序时,我得到这个异常:

A callback was made on a garbage collected delegate of type 'CaptureScreen!CaptureScreen.Form1+WinEventDelegate::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

在我的 program.cs 中的这一行:

Application.Run(new Form1());

我的Form1.cs(设计器本身没有控件)

    using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;

namespace CaptureScreen
{
public partial class Form1 : Form
{
private const uint WINEVENT_OUTOFCONTEXT = 0;
private const uint EVENT_SYSTEM_FOREGROUND = 3;
private const int WH_MOUSE_LL = 14;
private const int WM_LBUTTONDOWN = 513;

delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

IntPtr m_hhook;

[DllImport("user32.dll")]
static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

public Form1()
{
m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);

hookProc = new HookProc(LowLevelMouseProc);
hook = SetWindowsHookEx(WH_MOUSE_LL, hookProc, GetModuleHandle(null), 0);

InitializeComponent();
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
UnhookWinEvent(m_hhook);
UnhookWindowsHookEx(hook);
}

void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (eventType == EVENT_SYSTEM_FOREGROUND)
{
StringBuilder sb = new StringBuilder(500);
GetWindowText(hwnd, sb, sb.Capacity);
}
}

[DllImport("kernel32.dll")]
static extern IntPtr GetModuleHandle(string moduleName);

[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll")]
public static extern int UnhookWindowsHookEx(IntPtr hhook);

[DllImport("user32.dll")]
static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, uint wParam, IntPtr lParam);
delegate IntPtr HookProc(int nCode, uint wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();

private HookProc hookProc;
private IntPtr hook;

IntPtr LowLevelMouseProc(int nCode, uint wParam, IntPtr lParam)
{
if (nCode >= 0 && (IntPtr)wParam == (IntPtr)WM_LBUTTONDOWN)
{
CaptureScreen();
}
return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
}

private void CaptureScreen()
{
StreamReader reader = new StreamReader(Path.GetFullPath("../../Counter.txt"));
string currentpic = reader.ReadLine();
if (string.IsNullOrEmpty(currentpic))
currentpic = "0";
reader.Close();

Bitmap bitmap = Direct3DCapture.CaptureWindow(GetForegroundWindow());
bitmap.Save(Path.GetFullPath("../../ScreenCapture/Test" + currentpic + ".gif"), ImageFormat.Gif);

StreamWriter writer = new StreamWriter(Path.GetFullPath("../../Counter.txt"));
writer.Write((int.Parse(currentpic)) + 1);
writer.Close();
}

public readonly uint DWM_EC_DISABLECOMPOSITION = 0;
public readonly uint DWM_EC_ENABLECOMPOSITION = 1;
[DllImport("dwmapi.dll", EntryPoint = "DwmEnableComposition")]
protected static extern uint Win32DwmEnableComposition(uint uCompositionAction);
}
}

捕获屏幕的类可以在这里找到: http://spazzarama.wordpress.com/2009/02/07/screencapture-with-direct3d/

关于如何解决这个问题的任何想法?

最佳答案

您的问题是您只是将 WinEventProc 传递给 SetWinEventHook,这将隐式创建一个委托(delegate),该委托(delegate)有资格在当前方法退出后(如果不是更早的话!)被 GC 处理。您将看到该事实的后果。

您需要创建一个 WinEventDelegate 类型的 Form1 的新成员,并将其用作参数:

private WinEventDelegate winEventProc;

然后在调用 SetWinEventHook 时使用它:

this.winEventProc = new WinEventDelegate(WinEventProc);
m_hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, this.winEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);

这应该确保您的代理人在您需要的时候一直存活。

关于c# - CallbackOnCollectedDelegate 在 Application.Run(new Form1()),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6145823/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com