目标是
我想更改在 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 等,不起作用!!)
再次,我的问题
如何更改以不同用户帐户运行的其他应用程序的窗口不透明度?
感谢和抱歉我的英语不好:(。