【发布时间】:2013-09-06 02:05:55
【问题描述】:
我一直在为此苦苦挣扎,并查看了几篇推荐此作为正确程序的 stackoverflow 帖子:
Transparent window layer that is click-through and always stays on top
在我的代码中,我几乎完全遵循这种技术。然而,我的代码不起作用,我对为什么有点困惑。我想知道我是否使用了错误的程序?需要明确的是,我想要的效果是让用户单击我的表单并访问它下面的内容。例如,我在 Visual Studio 之上运行。如果我尝试点击该应用程序,我会改为点击 Visual Studio。
更新:
当我调用我的代码时,会发生以下两种情况之一(取决于我调用 setwindowlong 方法的位置):
- 窗口不绘制
- 窗口已绘制,但可点击
选项 1 发生在我在 initializecomponent 之后立即运行代码时 选项 2 在我在 initializecomponent 之前运行时发生
这是在其他任何事情之前绘制我的表单的完整代码:
[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);
public frmPhoneQueueViewer()
{
InitializeComponent();
// Set the form click-through
int initialStyle = GetWindowLong(this.Handle, -20);
SetWindowLong(this.Handle, -20, initialStyle | 0x80000 | 0x20);
//Get height of taskbar to exclude it, then bind to lower right of screen
int nTaskBarHeight = Screen.PrimaryScreen.Bounds.Bottom -Screen.PrimaryScreen.WorkingArea.Bottom;
Rectangle workingArea = Screen.GetWorkingArea(this);
this.Location = new Point(Screen.PrimaryScreen.Bounds.Right - this.Size.Width, workingArea.Bottom - Size.Height + nTaskBarHeight);
this.TopMost = true;
this.FormBorderStyle = FormBorderStyle.None;
this.ControlBox = false;
this.Text = string.Empty;
this.ShowInTaskbar = false;
PopulatePhoneQueueData();
}
【问题讨论】:
-
与问题无关,只是想知道如果用户的任务栏位于左侧/右侧/顶部而不是底部会发生什么?
-
怎么不工作?你应该描述细节。
-
检查
Handle是否已经创建。如果我没记错的话,窗体的构造函数中还没有创建窗口句柄。 -
来自文档:“CreateControl 方法强制为控件及其子控件创建句柄。当您需要立即使用句柄来操作控件或其子控件时使用此方法;只需调用控件的构造函数不会创建句柄。如果控件的 Visible 属性为 false,则 CreateControl 不会创建控件句柄。您可以调用 CreateHandle 方法或访问 Handle 属性来创建控件的句柄,而不管控件的可见性如何,但在在这种情况下,不会为控件的子级创建窗口句柄。"
-
另外,来自 Handle 属性文档:“Handle 属性的值是 Windows HWND。如果尚未创建句柄,则引用此属性将强制创建句柄。”