Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在c#中的另一个程序上创建非交互式图形覆盖?_C#_Image_Transparency_Non Interactive_Click Through - Fatal编程技术网

如何在c#中的另一个程序上创建非交互式图形覆盖?

如何在c#中的另一个程序上创建非交互式图形覆盖?,c#,image,transparency,non-interactive,click-through,C#,Image,Transparency,Non Interactive,Click Through,为了提供一些背景知识,我正在开发一款软件,帮助玩家玩《星球大战:旧共和国》。该游戏的用户界面功能非常有限,因此我正在开发一个外部应用程序,该应用程序将实时解析日志,并输出视觉线索,以帮助用户最大限度地提高游戏性能。例如,如果角色获得某个“buff”,战斗日志将显示它,我想在屏幕上放置一条视觉线索(因此用户不需要注意屏幕周边的小图标) 在我开始之前,我想为自己创建一些“概念验证”脚本,以了解如何交付主要部件。我一直坚持的是我的问题: 我需要能够显示一个图形,可能是一个透明的PNG文件,在游戏的屏幕

为了提供一些背景知识,我正在开发一款软件,帮助玩家玩《星球大战:旧共和国》。该游戏的用户界面功能非常有限,因此我正在开发一个外部应用程序,该应用程序将实时解析日志,并输出视觉线索,以帮助用户最大限度地提高游戏性能。例如,如果角色获得某个“buff”,战斗日志将显示它,我想在屏幕上放置一条视觉线索(因此用户不需要注意屏幕周边的小图标)

在我开始之前,我想为自己创建一些“概念验证”脚本,以了解如何交付主要部件。我一直坚持的是我的问题:

我需要能够显示一个图形,可能是一个透明的PNG文件,在游戏的屏幕上。用户需要能够点击该图像,以便继续与游戏交互。我有点不知道该怎么做。这些要求将是:

  • 显示一个图像(或多个图像)
  • 即使没有应用程序“焦点”,也要将该图像粘贴在其他应用程序的顶部
  • 使该图像为非交互式(或可点击)
  • 我正在用C语言开发应用程序#

任何关于从何处开始的指导都将不胜感激

我过去这样做的方法是获取主窗口的句柄,通常唯一的方法是遍历整个窗口列表,查找具有所需标题的窗口。如果有两个游戏实例同时以相同的标题打开,这是有问题的

一旦你有了这个窗口句柄,你就可以通过指定你希望它相对于窗口左上角的像素有多少个像素,有多少个像素在上面,有多少个像素在下面,还有多少层在外面(z索引)


多窗口的一种方法是启动您的c#程序,查看是否有游戏实例已在玩,发出消息,如果有则终止,如果没有,然后启动游戏实例作为子进程。我认为你可以在那时找回hwin,但如果没有,你可以在游戏运行后在窗口列表中搜索目标标题。

我已经开始考虑做一些类似的事情,因此这可能会给你一个开始

对于第一个版本,您可以从查看的“AllowTransparency”、“TransparencyKey”和“TopMost”属性开始

(我发现TransparencyKey不适用于白色(255255),但特定的非白色颜色可以很好地工作……不知道为什么)

这将作为一个可点击的表单,它将位于其他表单之上……但由于它是透明的,所以不能在透明部分显示图像。但是,如果您只需要一个适合目标应用程序的hud,那么这可能是最简单的方法

如果这个顶级表单没有出现在游戏前面…你可以尝试将游戏置于窗口模式

在全屏模式下运行时,游戏通常通过ActiveX、Direct3D、OpenGL、DirectDraw等直接绘制到屏幕上

在这些基础上绘图需要将代码注入DirectX、OpenGL或其他引擎的绘图/更新/刷新功能(基本上告诉DirectX3D在每个绘图周期结束时绘制您的内容)。有一些现有的软件可以做到这一点:例如,Steam Overlay、fraps、xfire

一个快速的谷歌搜索发现了“”,虽然我还没有下载或尝试过,但它说它可以为你在游戏上面覆盖表单应用程序

(似乎那个项目是由一家刚刚解散的公司管理的,我似乎无论如何都无法让它为我工作……)

可以创建一个不完全透明的表单,但可以通过本机Windows调用进行点击。我将在接下来的几天内看看是否可以创建一个示例


我找到了一个旧的测试项目,并对它进行了一些清理

基本上,当运行时,它会在屏幕前面随机画出500条红线,可以点击。然后,它随机绘制1000条白线(即擦除)。然后重复

在编写代码的过程中,我想从以下几个方面得到一个概念证明:如何能够在窗体的整个表面上绘制,如何通过编程使窗体在多个屏幕上变为全尺寸,如何使用后台工作人员,以及这个概念证明如何作为透明覆盖层工作

说明:

  • 创建名为TranparentOverlay_simpleExample的新Windows窗体项目
  • 在“设计”视图中,在Form1上设置以下属性:
    • 背景颜色:白色
    • FormBorderStyle:无
    • 位置:-1280,0(即屏幕的左上角,一个屏幕可能只有0,0)
    • 最上面的:真的
    • 透明键:白色
    • 窗口状态:最大化
现在输入Form1的代码视图,并将其替换为以下内容:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
namespace TransparentOverlay_simpleExample
{

    public partial class Form1 : Form
    {
        BackgroundWorker bw = new BackgroundWorker();
        Random rand = new Random(DateTime.Now.Millisecond);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool BringWindowToTop(IntPtr hWnd);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
        public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);



        [DllImport("user32.dll")]
        static extern int SendMessage(IntPtr hWnd, uint wMsg, UIntPtr wParam, IntPtr lParam); //used for maximizing the screen

        const int WM_SYSCOMMAND = 0x0112; //used for maximizing the screen.
        const int myWParam = 0xf120; //used for maximizing the screen.
        const int myLparam = 0x5073d; //used for maximizing the screen.


        int oldWindowLong;

        [Flags]
        enum WindowStyles : uint
        {
            WS_OVERLAPPED = 0x00000000,
            WS_POPUP = 0x80000000,
            WS_CHILD = 0x40000000,
            WS_MINIMIZE = 0x20000000,
            WS_VISIBLE = 0x10000000,
            WS_DISABLED = 0x08000000,
            WS_CLIPSIBLINGS = 0x04000000,
            WS_CLIPCHILDREN = 0x02000000,
            WS_MAXIMIZE = 0x01000000,
            WS_BORDER = 0x00800000,
            WS_DLGFRAME = 0x00400000,
            WS_VSCROLL = 0x00200000,
            WS_HSCROLL = 0x00100000,
            WS_SYSMENU = 0x00080000,
            WS_THICKFRAME = 0x00040000,
            WS_GROUP = 0x00020000,
            WS_TABSTOP = 0x00010000,

            WS_MINIMIZEBOX = 0x00020000,
            WS_MAXIMIZEBOX = 0x00010000,

            WS_CAPTION = WS_BORDER | WS_DLGFRAME,
            WS_TILED = WS_OVERLAPPED,
            WS_ICONIC = WS_MINIMIZE,
            WS_SIZEBOX = WS_THICKFRAME,
            WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW,

            WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
            WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
            WS_CHILDWINDOW = WS_CHILD,

            //Extended Window Styles

            WS_EX_DLGMODALFRAME = 0x00000001,
            WS_EX_NOPARENTNOTIFY = 0x00000004,
            WS_EX_TOPMOST = 0x00000008,
            WS_EX_ACCEPTFILES = 0x00000010,
            WS_EX_TRANSPARENT = 0x00000020,

            //#if(WINVER >= 0x0400)

            WS_EX_MDICHILD = 0x00000040,
            WS_EX_TOOLWINDOW = 0x00000080,
            WS_EX_WINDOWEDGE = 0x00000100,
            WS_EX_CLIENTEDGE = 0x00000200,
            WS_EX_CONTEXTHELP = 0x00000400,

            WS_EX_RIGHT = 0x00001000,
            WS_EX_LEFT = 0x00000000,
            WS_EX_RTLREADING = 0x00002000,
            WS_EX_LTRREADING = 0x00000000,
            WS_EX_LEFTSCROLLBAR = 0x00004000,
            WS_EX_RIGHTSCROLLBAR = 0x00000000,

            WS_EX_CONTROLPARENT = 0x00010000,
            WS_EX_STATICEDGE = 0x00020000,
            WS_EX_APPWINDOW = 0x00040000,

            WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE),
            WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST),
            //#endif /* WINVER >= 0x0400 */

            //#if(WIN32WINNT >= 0x0500)

            WS_EX_LAYERED = 0x00080000,
            //#endif /* WIN32WINNT >= 0x0500 */

            //#if(WINVER >= 0x0500)

            WS_EX_NOINHERITLAYOUT = 0x00100000, // Disable inheritence of mirroring by children
            WS_EX_LAYOUTRTL = 0x00400000, // Right to left mirroring
            //#endif /* WINVER >= 0x0500 */

            //#if(WIN32WINNT >= 0x0500)

            WS_EX_COMPOSITED = 0x02000000,
            WS_EX_NOACTIVATE = 0x08000000
            //#endif /* WIN32WINNT >= 0x0500 */

        }

        public enum GetWindowLongConst
        {
            GWL_WNDPROC = (-4),
            GWL_HINSTANCE = (-6),
            GWL_HWNDPARENT = (-8),
            GWL_STYLE = (-16),
            GWL_EXSTYLE = (-20),
            GWL_USERDATA = (-21),
            GWL_ID = (-12)
        }

        public enum LWA
        {
            ColorKey = 0x1,
            Alpha = 0x2,
        }

        [DllImport("user32.dll", SetLastError = true)]
        static extern int GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll")]
        static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

        [DllImport("user32.dll")]
        static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);

        /// <summary>
        /// Make the form (specified by its handle) a window that supports transparency.
        /// </summary>
        /// <param name="Handle">The window to make transparency supporting</param>
        public void SetFormTransparent(IntPtr Handle)
        {
            oldWindowLong = GetWindowLong(Handle, (int)GetWindowLongConst.GWL_EXSTYLE);
            SetWindowLong(Handle, (int)GetWindowLongConst.GWL_EXSTYLE, Convert.ToInt32( oldWindowLong | (uint)WindowStyles.WS_EX_LAYERED | (uint)WindowStyles.WS_EX_TRANSPARENT));
        }

        /// <summary>
        /// Make the form (specified by its handle) a normal type of window (doesn't support transparency).
        /// </summary>
        /// <param name="Handle">The Window to make normal</param>
        public void SetFormNormal(IntPtr Handle)
        {
            SetWindowLong(Handle, (int)GetWindowLongConst.GWL_EXSTYLE, Convert.ToInt32(oldWindowLong | (uint)WindowStyles.WS_EX_LAYERED));
        }

        /// <summary>
        /// Makes the form change White to Transparent and clickthrough-able
        /// Can be modified to make the form translucent (with different opacities) and change the Transparency Color.
        /// </summary>
        public void SetTheLayeredWindowAttribute()
        {
            uint transparentColor = 0xffffffff;

            SetLayeredWindowAttributes(this.Handle, transparentColor, 125, 0x2);

            this.TransparencyKey = Color.White;
        }

        /// <summary>
        /// Finds the Size of all computer screens combined (assumes screens are left to right, not above and below).
        /// </summary>
        /// <returns>The width and height of all screens combined</returns>
        public static Size getFullScreensSize()
        {
            int height = int.MinValue;
            int width = 0;

            foreach (Screen screen in System.Windows.Forms.Screen.AllScreens)
            {
                //take largest height
                height = Math.Max(screen.WorkingArea.Height, height);

                width += screen.Bounds.Width;
            }

            return new Size(width, height);
        }

        /// <summary>
        /// Finds the top left pixel position (with multiple screens this is often not 0,0)
        /// </summary>
        /// <returns>Position of top left pixel</returns>
        public static Point getTopLeft()
        {
            int minX = int.MaxValue;
            int minY = int.MaxValue;

            foreach (Screen screen in System.Windows.Forms.Screen.AllScreens)
            {
                minX = Math.Min(screen.WorkingArea.Left, minX);
                minY = Math.Min(screen.WorkingArea.Top, minY);
            }

            return new Point( minX, minY );
        }

        public Form1()
        {
            InitializeComponent();

            MaximizeEverything();

            SetFormTransparent(this.Handle);

            SetTheLayeredWindowAttribute();

            BackgroundWorker tmpBw = new BackgroundWorker();
            tmpBw.DoWork += new DoWorkEventHandler(bw_DoWork);

            this.bw = tmpBw;

            this.bw.RunWorkerAsync();
        }

        private void MaximizeEverything()
        {
            this.Location = getTopLeft();
            this.Size = getFullScreensSize();

            SendMessage(this.Handle, WM_SYSCOMMAND, (UIntPtr)myWParam, (IntPtr)myLparam);
        }

        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            int numRedLines = 500;
            int numWhiteLines = 1000;

            Size fullSize = getFullScreensSize();
            Point topLeft = getTopLeft();

            using (Pen redPen = new Pen(Color.Red, 10f), whitePen = new Pen(Color.White, 10f)) {
                using (Graphics formGraphics = this.CreateGraphics()) {

                    while (true) {

                        bool makeRedLines = true;

                        for (int i = 0; i < numRedLines + numWhiteLines; i++)
                        {

                            if (i > numRedLines)
                            {
                                makeRedLines = false;
                            }

                            //Choose points for random lines...but don't draw over the top 100 px of the screen so you can 
                            //still find the stop run button.
                            int pX = rand.Next(0, (-1 * topLeft.X) + fullSize.Width);
                            int pY = rand.Next(100, (-1 * topLeft.Y) + fullSize.Height);

                            int qX = rand.Next(0, (-1 * topLeft.X) + fullSize.Width);
                            int qY = rand.Next(100, (-1 * topLeft.Y) + fullSize.Height);

                            if (makeRedLines)
                            {
                                formGraphics.DrawLine(redPen, pX, pY, qX, qY);
                            }
                            else
                            {
                                formGraphics.DrawLine(whitePen, pX, pY, qX, qY);
                            }

                            Thread.Sleep(10);
                        }
                    }
                }
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
使用系统线程;
使用System.Runtime.InteropServices;
名称空间透明verlay_simpleExample
{
公共部分类Form1:Form
{
BackgroundWorker bw=新的BackgroundWorker();
Random rand=新随机数(DateTime.Now.毫秒);
[DllImport(“user32.dll”)]
[返回:Marshallas(UnmanagedType.Bool)]
静态外部布尔布林温多图(IntPtr hWnd);
[DllImport(“user32.dll”)]
[返回:Marshallas(UnmanagedType.Bool)]
静态外部bool setforegroundindow(IntPtr hWnd);
[DllImport(“使用