2

我的总体目标是渲染第二个(或第三个、第四个……)鼠标光标。为此,我创建了一个无框、最顶层、透明的窗口。我可以在这个窗口上绘图(我有 4 个按钮来显示它正确地覆盖了整个桌面) - 但是当我单击任务栏时,它会被带到顶部并覆盖我的按钮和绘制的线条。

如何将窗口保持在任务栏上方

或者,有没有办法可以在屏幕的“最终”版本上绘图?

这是我的 .Designer.cs 文件中的代码:

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.White;
this.CausesValidation = false;
this.ClientSize = new System.Drawing.Size(332, 332);
this.ControlBox = false;
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Screen";
this.ShowIcon = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultBounds;
this.TopMost = true;
this.TransparencyKey = System.Drawing.Color.White;
4

4 回答 4

2

在不分析这样做的确切动机以及这种方法是否是最佳方式的情况下,您应该注意任务栏的行为与任何其他窗口的行为相同:TopMost可以不受任何限制地使用。另一方面,它被认为在“WorkingArea”之外,因此,根据您使用的属性,它可能会被忽略。查看下面的示例代码以更好地理解这一点。

Main Form覆盖任务栏上方的所有可用空间:

this.ClientSize = new System.Drawing.Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Left, Screen.PrimaryScreen.WorkingArea.Top);

Main Form覆盖屏幕的整个可用空间:

this.ClientSize = new System.Drawing.Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Left, Screen.PrimaryScreen.WorkingArea.Top);

因此,通过记住它代表屏幕之间的差异WorkingArea,您可以毫无问题地将表单定位在任务栏的顶部。Bounds

澄清:这个答案强调了任务栏与屏幕任何其他部分的处理方式不同的原因。这并不意味着您必须使表单与整个屏幕一样大才能将其放在任务栏上;您可以随时将它放在任务栏上,大小随心所欲。您必须记住的是,WorkingArea它不提供屏幕的整个尺寸,而只是提供任务栏上方的区域;如果要考虑任务栏,请考虑Bounds.

于 2013-08-31T08:06:15.320 回答
1

我会选择 varocarbas 的答案,但是我想添加一些我认为可能有用的东西。

我想有几件事可能会有所帮助,当我阅读您的问题时,我想到的第一个想法是创建一条GlobalHook监视消息WM_CBT,当系统即将进入窗口时,此消息将发送到 GlobalHook 过程。当Maximize,Minimize,Restore or Focus任何钩子被困住了,您可以覆盖任何必需的事件以阻止该窗口成为最顶层的窗口,从而your Form有机会保持最顶层的窗口。如果它按我的预期工作,此方法将非常有用。

如果您对此感兴趣,这里是使 GlobalHook 工作所需的方法。 SetWindowsHookEx(),用于告诉系统创建一个 GlobalHook。
HookProc,表示钩子捕捉到被监控事件时调用的方法。
HookType,枚举传递给 SetWindowsHookEx 调用的有效挂钩类型。
CallNextHook。如果使用互操作性很麻烦,试试这个开源库,它在托管包装器中包含 WindowsAPI 函数。希望这对你有帮助,同时我也在努力让这些东西为你工作。

于 2013-08-31T08:52:50.083 回答
1

我已经为同样的问题苦苦挣扎了几个小时。我想到了一个不错的解决方案:只要表单最大化,就动态更改表单的底部填充。

If Me.WindowState = FormWindowState.Maximized then
    Dim pd As New Padding
    pd.Left = Me.Padding.Left
    pd.Right = Me.Padding.Right
    pd.Top = Me.Padding.Top
    pd.Bottom = Me.Height - Screen.PrimaryScreen.WorkingArea.Height
    Me.Padding = pd
end if

这样表单不在任务栏上方,但至少您的控件在!注意:在设计表单时,您可以将底部填充保留为 0。如果您希望表单能够最小化/正常调整大小,那么您可能希望在另一个表单事件中将底部填充重置为 0。

于 2013-12-05T14:12:20.280 回答
0

我实际上在发布后大约 15 分钟找到了解决方案。(不总是这样吗?研究了几个小时,但一旦你寻求帮助,你就会自己解决。:)

我有一个事件通过位置更新调用我的代码。如果我在这个事件中简单地调用“BringToFront”,它工作得很好。该事件每秒被调用多次,但如果我将我的行为限制到 1/4 秒,它仍然可以正常工作。

于 2013-08-31T20:56:19.207 回答