ackOnCollectedDelegate在Applicati

ackOnCollectedDelegate在Applicati

本文介绍了CallbackOnCollectedDelegate在Application.Run(new Form1())的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我做了一个非常小的应用程序,使用SlimDX捕获游戏中的屏幕。
(我按左键捕获)

I made a very small application that captures the screen inside games using SlimDX.(I press left click to capture)

捕获工作(至少当我点击表单本身),但一旦我点击Firefox或任何其他应用程序,我得到这个例外:

The capture works (atleast when I click on the form itself) but as soon as I click on firefox or any other application, I get this exception :

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

at this line in my program.cs:

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

My Form1.cs (the designer itself has no controls)

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

可以在这里找到捕获屏幕的类:

the class that captures the screen can be found here:http://spazzarama.wordpress.com/2009/02/07/screencapture-with-direct3d/

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

Any idea on how I can fix this?

推荐答案

您的问题是您只是将WinEventProc传递给SetWinEventHook,它将隐式创建一个当前方法退出时有资格进行GCed的代理(如果不是更快)看到这个事实的后果。

Your problem is that you are just passing WinEventProc to SetWinEventHook, which will implicitly create a delegate that is eligible to be GCed once the current method exits (if not sooner!) You are seeing the consequences of that fact.

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

You will need to create a new member of Form1 of type WinEventDelegate, and use that as the parameter:

private WinEventDelegate winEventProc;

然后在调用SetWinEventHook时使用它:

and then make use of it in your call to SetWinEventHook:

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

应该确保您的代理在需要时保持活着。

That should ensure that your delegate stays alive as long as you need.

这篇关于CallbackOnCollectedDelegate在Application.Run(new Form1())的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 02:41