SetWindowLong& SetLayeredWindowAttributes不适用于不同的用户C#

时间:2013-03-08 04:36:27

标签: api windows-xp opacity alpha setwindowlong

目标是

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

情况

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

问题和我的问题

SetWindowLong& SetLayeredWindowAttributes不适用于以其他用户帐户身份运行的目标应用程序。但它适用于在同一用户帐户(已记录的用户帐户)下运行的目标应用程序

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

插图应用

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

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

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 ..

Instance1

  • 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等,不起作用!!)

再次,我的问题

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

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

0 个答案:

没有答案