2

我正在尝试将表单固定到桌面,例如小工具侧边栏。

它不应受 Win+D 和显示桌面按钮的影响。

哪个是最好的方法?

我可以找到 Progman 并将我的表单的父级设置为此,但我读到这不是最好的方法。

4

6 回答 6

5

免责声明:仅仅因为您可以在 WinForms 中以某种方式在没有 API 调用或“挂钩”的情况下做某事,并不意味着您应该使用该技术。使窗体/窗口不可移动、最顶层等的 API 调用非常简单。请注意,通常的 API“简单技术”与下面演示的技术存在相同的问题,即出现在桌面上的文件和文件夹图标上。

请注意,通过“干扰” Windows-D 组合键和任务栏中的“显示桌面”图标-hickey 的设计行为,您正在对用户机器进行非标准配置:常见的“智慧”表明它不是这样做是个好主意!

可以在 C# WinForms 中的 Vista 中模拟“伪侧边栏”...不受 Windows-D 隐藏或在系统托盘中使用“显示桌面”图标-hickey ...无需 API 调用或“挂钩” :但有一个问题:窗体/窗口将出现在桌面上的项目(文件夹、文件)之上,并且由于它是不可移动的,您将无法访问“它下面的项目”。 " 如果您愿意“忍受”该限制:请继续阅读:) 在本文末尾指出的另一个“较小的怪异”。

例子 :

  1. 在 Visual Studio 中创建一个新的表单解决方案:

    一种。设置窗体的大小、背景颜色等以品尝

    湾。添加您的控件或用户控件。

    C。将 Form 的 'TopMost 属性设置为 'true 如果您希望始终出现在其他应用程序的窗口前面,如果您希望其他应用程序的窗口能够出现在它前面,则设置为 false。

  2. 将 Form 的 'ControlBox、'MinimizeBox 和 'MaximizeBox 属性设置为 'false。

  3. 将“FormBorderStyle”设置为“属性资源管理器”下拉列表中显示的“固定样式”之一。正如您可能知道的那样,使用 FormBorderStyle = FixedToolWindow 和 Form 的 Text 属性是一个“空字符串”:您将拥有一个没有 TitleBar 和 Caption 的窗口。讨论:是的,如果您愿意,您可以允许调整它的大小:只需在 SizeChanged 处理程序中编写一些代码,然后让表单保持解锁状态。

  4. 这些事件处理程序应该让您了解使表单不可关闭、不可移动、不可最小化等所需的内容。

.........粗略的草图代码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]

于 2010-01-17T14:11:22.897 回答
2

听起来您所追求的是Application Desktop Toolbar

于 2010-01-17T16:17:11.127 回答
1

我可能是错的,但可能是 Win+D 可能会向所有打开的窗口发送全局最小化消息

因此,请尝试使您的表单不受窗口最小化消息的影响。使用钩子

这是一篇相关文章。

挂钩

于 2010-01-17T13:17:46.213 回答
0

谢谢大家的回答,

起初我有这个方法:

    [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);

但主要问题是子窗口也是桌面的父窗口,您不能使用任何形式的不透明度或透明度。

于 2010-01-18T10:57:36.480 回答
0

使用以下代码并将窗口句柄传递给函数,同时表单加载希望完全解决您的问题

public void SetFormOnDesktop(IntPtr hwnd) {      
IntPtr hwndf = hwnd;
IntPtr hwndParent = FindWindow("ProgMan", null);
SetParent(hwndf, hwndParent);
}
于 2010-05-05T06:36:32.053 回答
0

一个简单的解决方法可能是只使用 Win+M 而不要听停用事件。这将消除激活/停用的闪烁。

于 2014-01-24T10:16:44.817 回答