我正在尝试将表单固定到桌面,例如小工具侧边栏。
它不应受 Win+D 和显示桌面按钮的影响。
哪个是最好的方法?
我可以找到 Progman 并将我的表单的父级设置为此,但我读到这不是最好的方法。
免责声明:仅仅因为您可以在 WinForms 中以某种方式在没有 API 调用或“挂钩”的情况下做某事,并不意味着您应该使用该技术。使窗体/窗口不可移动、最顶层等的 API 调用非常简单。请注意,通常的 API“简单技术”与下面演示的技术存在相同的问题,即出现在桌面上的文件和文件夹图标上。
请注意,通过“干扰” Windows-D 组合键和任务栏中的“显示桌面”图标-hickey 的设计行为,您正在对用户机器进行非标准配置:常见的“智慧”表明它不是这样做是个好主意!
可以在 C# WinForms 中的 Vista 中模拟“伪侧边栏”...不受 Windows-D 隐藏或在系统托盘中使用“显示桌面”图标-hickey ...无需 API 调用或“挂钩” :但有一个问题:窗体/窗口将出现在桌面上的项目(文件夹、文件)之上,并且由于它是不可移动的,您将无法访问“它下面的项目”。 " 如果您愿意“忍受”该限制:请继续阅读:) 在本文末尾指出的另一个“较小的怪异”。
例子 :
在 Visual Studio 中创建一个新的表单解决方案:
一种。设置窗体的大小、背景颜色等以品尝
湾。添加您的控件或用户控件。
C。将 Form 的 'TopMost 属性设置为 'true 如果您希望始终出现在其他应用程序的窗口前面,如果您希望其他应用程序的窗口能够出现在它前面,则设置为 false。
将 Form 的 'ControlBox、'MinimizeBox 和 'MaximizeBox 属性设置为 'false。
将“FormBorderStyle”设置为“属性资源管理器”下拉列表中显示的“固定样式”之一。正如您可能知道的那样,使用 FormBorderStyle = FixedToolWindow 和 Form 的 Text 属性是一个“空字符串”:您将拥有一个没有 TitleBar 和 Caption 的窗口。讨论:是的,如果您愿意,您可以允许调整它的大小:只需在 SizeChanged 处理程序中编写一些代码,然后让表单保持解锁状态。
这些事件处理程序应该让您了解使表单不可关闭、不可移动、不可最小化等所需的内容。
.........粗略的草图代码poc如下:显然你可以重构,改进......
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
}
// set your Form's 'Top here ...
private void Form1_LocationChanged(object sender, EventArgs e)
{
this.Top = 100;
this.Left = Screen.PrimaryScreen.Bounds.Width - this.Width;
}
private void Form1_VisibleChanged(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal;
}
private void Form1_Deactivate(object sender, EventArgs e)
{
this.Activate();
}
private void Form1_SizeChanged(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized) this.WindowState = FormWindowState.Normal;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("button1 is alive");
}
'button1 的'Click 事件处理程序在那里做什么?只是为了在我的测试中验证表单是否可用。
这是在上面的“停用事件处理程序”中重新激活表单,使表单不受 Windows-D 和“显示桌面”的影响:但这在 Vista 中也有一个奇怪的副作用:当您将焦点从表单的窗口(例如,通过单击桌面上的文件夹):任务栏会弹起,保持不动,(如果它是隐藏的)并闪烁一会儿:我想向您展示它渴望活跃。
忍受卡住打开的任务栏可能是使用这个“ersatz 侧边栏”而不使用 API 的另一个代价。
注意:不要忘记:你想要'不透明度:你有'不透明度:)
[1] 注意:您是否想考虑为用户提供一种隐藏或关闭表单的方法?[/1]
听起来您所追求的是Application Desktop Toolbar。
谢谢大家的回答,
起初我有这个方法:
[DllImport("User32.dll")]
static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
static extern int SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
IntPtr pWnd = FindWindow("Progman", null);
pWnd = FindWindowEx(pWnd, IntPtr.Zero, "SHELLDLL_DefVIew", null);
pWnd = FindWindowEx(pWnd, IntPtr.Zero, "SysListView32", null);
IntPtr tWnd = this.Handle;
SetParent(tWnd, pWnd);
但主要问题是子窗口也是桌面的父窗口,您不能使用任何形式的不透明度或透明度。
使用以下代码并将窗口句柄传递给函数,同时表单加载希望完全解决您的问题
public void SetFormOnDesktop(IntPtr hwnd) {
IntPtr hwndf = hwnd;
IntPtr hwndParent = FindWindow("ProgMan", null);
SetParent(hwndf, hwndParent);
}
一个简单的解决方法可能是只使用 Win+M 而不要听停用事件。这将消除激活/停用的闪烁。