2

目标是

我想更改在 win xp 上运行的某些应用程序(目标)的不透明度。

情况

  • 我以 AD (active dir) 用户帐户 (some-domain\username) 登录 win xp
  • 大多数目标应用程序以本地用户或其他广告用户身份运行

问题和我的问题

SetWindowLong&SetLayeredWindowAttributes不适用于作为其他用户帐户运行的目标应用程序。但它适用于在同一用户帐户下运行的目标应用程序(登录用户帐户)

如何更改以不同用户帐户运行的其他应用程序的窗口不透明度?

插图应用

这是一个获胜表单应用程序(我们称之为 OpaciToggler.exe)。我有 2 个按钮(btnRunSomething 和 btnHideThatThing)和一个文本框(txtPid)。就如此容易。

当我单击 btnRunSomething 时,它以不同的用户身份运行 .exe。所有详细信息都在 app.config 中。在这种情况下,我以不同的用户 (localComputer\user1) 运行此应用程序(OpaciToggler.exe,来自 debug/bin)

txtPid 用于手动输入 pid。通常我打开任务管理器(win > run > taskmgr)并找到我想要测试的任何应用程序(目标)的pid(在进程选项卡下),然后在此处输入。

当我单击 btnHideThatThing 时,它将切换目标应用程序的不透明度(其 pid 在 txtPid 中)

代码 C#

这就是我调用目标应用程序的方式。

    private void btnRunSomething_Click(object sender, EventArgs e)
    {
        System.Diagnostics.Process p = new System.Diagnostics.Process();

        p.StartInfo.Domain = ConfigurationManager.AppSettings["StartInfoDomain"]; 
        p.StartInfo.UserName = ConfigurationManager.AppSettings["StartInfoUserName"]; 

        p.StartInfo.FileName = ConfigurationManager.AppSettings["StartInfoFileName"];
        p.StartInfo.Arguments = ConfigurationManager.AppSettings["StartInfoArguments"];

        System.String rawPassword = ConfigurationManager.AppSettings["StartInfoPassword"];
        System.Security.SecureString encPassword = new System.Security.SecureString();

        foreach (System.Char c in rawPassword)
        {
            encPassword.AppendChar(c);
        }

        p.StartInfo.Password = encPassword;
        p.StartInfo.UseShellExecute = false;

        p.Start();
    }

这就是我尝试调用不透明度的方式

    private void btnHideThatThing_Click(object sender, EventArgs e)
    {
        // manual input pid 
        int pid = int.Parse(txtPid.Text);
        IntPtr mwh = Process.GetProcessById(pid).MainWindowHandle;
        doHideThing(mwh);  

        // doHideThing(Process.GetProcessById(int.Parse(txtPid.Text)).MainWindowHandle);
    }

隐藏方法

    private void doHideThing(IntPtr hndl)
    {
        SetWindowLong(hndl, GWL_EXSTYLE, GetWindowLong(hndl, GWL_EXSTYLE) ^ WS_EX_LAYERED).ToString();
        // _whatNow = Marshal.GetLastWin32Error();

        SetLayeredWindowAttributes(hndl, 0, (255 * 20) / 100, LWA_ALPHA).ToString();
        // _whatNow = Marshal.GetLastWin32Error();

        RedrawWindow(hndl, IntPtr.Zero, IntPtr.Zero,
            RedrawWindowFlags.Erase | RedrawWindowFlags.Invalidate |
            RedrawWindowFlags.Frame | RedrawWindowFlags.AllChildren);            
    }

其他代码

    private const int GWL_EXSTYLE = -20;
    private const int GWL_STYLE = -16;
    private const int WS_EX_LAYERED = 0x80000;
    private const int LWA_ALPHA = 0x2;
    private const int LWA_COLORKEY = 0x1;

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

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

    [DllImport("user32.dll", SetLastError = true)]
    static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, RedrawWindowFlags flags);

RedrawWindowFlags 枚举(我不记得我从哪里得到的)

[Flags()]
enum RedrawWindowFlags : uint
{
    /// <summary>
    /// Invalidates the rectangle or region that you specify in lprcUpdate or hrgnUpdate.
    /// You can set only one of these parameters to a non-NULL value. If both are NULL, RDW_INVALIDATE invalidates the entire window.
    /// </summary>
    Invalidate = 0x1,

    /// <summary>Causes the OS to post a WM_PAINT message to the window regardless of whether a portion of the window is invalid.</summary>
    InternalPaint = 0x2,

    /// <summary>
    /// Causes the window to receive a WM_ERASEBKGND message when the window is repainted.
    /// Specify this value in combination with the RDW_INVALIDATE value; otherwise, RDW_ERASE has no effect.
    /// </summary>
    Erase = 0x4,

    /// <summary>
    /// Validates the rectangle or region that you specify in lprcUpdate or hrgnUpdate.
    /// You can set only one of these parameters to a non-NULL value. If both are NULL, RDW_VALIDATE validates the entire window.
    /// This value does not affect internal WM_PAINT messages.
    /// </summary>
    Validate = 0x8,

    NoInternalPaint = 0x10,

    /// <summary>Suppresses any pending WM_ERASEBKGND messages.</summary>
    NoErase = 0x20,

    /// <summary>Excludes child windows, if any, from the repainting operation.</summary>
    NoChildren = 0x40,

    /// <summary>Includes child windows, if any, in the repainting operation.</summary>
    AllChildren = 0x80,

    /// <summary>Causes the affected windows, which you specify by setting the RDW_ALLCHILDREN and RDW_NOCHILDREN values, to receive WM_ERASEBKGND and WM_PAINT messages before the RedrawWindow returns, if necessary.</summary>
    UpdateNow = 0x100,

    /// <summary>
    /// Causes the affected windows, which you specify by setting the RDW_ALLCHILDREN and RDW_NOCHILDREN values, to receive WM_ERASEBKGND messages before RedrawWindow returns, if necessary.
    /// The affected windows receive WM_PAINT messages at the ordinary time.
    /// </summary>
    EraseNow = 0x200,

    Frame = 0x400,

    NoFrame = 0x800
}

示例、测试和测试结果

  • 以 domainA\ad_user1 身份登录 win xp
  • 运行 OpaciToggler.exe 应用程序(Instance1,作为 domainA\ad_user1 运行)
  • 然后我点击运行一些东西。它会打开另一个 OpaciToggler.exe (Instance2),作为另一个用户帐户运行(作为 localcomputer\l_user1 运行)或右键单击 .exe,然后单击 run as..

实例1

  • PID:1234
  • 运行为:domainA\ad_user1
  • txtPid: 5678 (Instance2, 不工作)
  • txtPid:1234(自我,作品)
  • txtPid:任何 pid 作为同一个帐户运行(例如:notepad.exe、calc.exe 等都可以)

实例2

  • PID:5678
  • 运行为:localcomputer\l_user1
  • txtPid:1234(实例1,不起作用)
  • txtPid:5678(自我,作品)
  • txtPid:任何 pid 以同一帐户运行 (localcomputer\l_user1)(例如:notepad.exe、calc.exe 等,不起作用!!)

再次,我的问题

如何更改以不同用户帐户运行的其他应用程序的窗口不透明度?

感谢和抱歉我的英语不好:(。

4

0 回答 0