构建 Microsoft Gadget 克隆(v 1)
一个 Windows 窗体用户控件,克隆了 Microsoft 侧边栏小组件的一些功能。



引言
有了 Windows Vista,我立即对构建和发布侧边栏小工具产生了兴趣。那些整洁的、无框的应用程序,放置在我的显示器各处,确实为沉闷的传统 Windows 桌面增添了色彩。
很快我就厌倦了编写 HTML、CSS 和 JavaScript。毕竟,难道我还没有转向 C# 和 .NET 这样更好的东西吗?当然我了解,是的,我也做过。当然,我说的是 Interop ActiveX 编程以及用 JavaScript “即时” 注册我的程序。但即便如此,我仍然对这些限制和令人疲惫的调试功能感到不满意,所以,我回到了 Windows Forms 的怀抱。只是这一次,我决定在我的 Windows Forms 中使用一些小工具的特性。这些都捆绑在一个易于使用的 Windows Forms 用户控件中。它们包括:
- 一个弹出侧边菜单,带有“关闭”、“设置”、“关于”和“移动”按钮
- 显示“设置”和“关于”窗体时的缩略图
- 主窗口的自动定位
- “弹出窗口”和其他对话框的自动定位
库的实现
首先,在图形程序中,例如 Paint.Net,创建您的小工具的背景图像。
将图像的右侧扩展 24 像素,以便添加克隆用户控件。此区域应用背景色 `TransparencyKey` 填充。在这种情况下,我选择 RGB 255; 0; 220。

创建一个新的 VS Windows Forms 项目。
通过将项目的 `FormBorderStyle` 设置为“None
”来使项目窗体无边框。

将窗体调整为背景图像的高度和宽度。

将背景图像导入到您的项目中,并将窗体的背景设置为背景
图像。

设置窗体的 `TransparencyKey` 颜色。

下载并保存 `gadgetControll` 库。
在 Visual Studio 的解决方案资源管理器中,添加对 `gadgetControl` 库的引用。
在窗体的类中,创建“gadgetClone
”控件的实例。
public partial class Form1 : Form
{
/*==============================================
* create an instance of the control
* ============================================= */
private gadgetControlsLibrary.gadgetClone gclone
= new gadgetControlsLibrary.gadgetClone();
在窗体的构造函数中,添加“gadgetClone
”控件。
设置属性以确定要在弹出侧边菜单上显示哪些可选按钮。“AltSizeButton” 应设置为 false。“关闭”和“移动”始终显示。
为弹出侧边菜单中显示的所有按钮创建 `EventHandlers`。如果您希望在移动窗体后执行某些操作,请为“moveLeftMouseUp
”创建一个 `EventHandler`。例如,保存窗体的坐标以供下次应用程序启动时定位。
初始化 `PopOut` 菜单。
public Form1()
{
InitializeComponent();
/*==============================================
* add the control to your form
* ============================================= */
this.Controls.Add(gclone);
/*==============================================
* set which optional buttons to show
* and initialize the popout side menu
* "Close" and "Move" are always shown.
* ============================================= */
gclone.showAboutButton = true;
gclone.showAltSizeButton = false; // (currently notifyIcon1 supported)
gclone.showSettingsButton = true;
gclone.initializePopOutMenu();
/*==============================================
* define event handlers to handle "Click" events
* from all of the shown buttons
* ============================================= */
gclone.closeClicked += new EventHandler(gclone_closeClicked);
gclone.settingsClicked += new EventHandler(gclone_settingsClicked);
gclone.aboutClicked += new EventHandler(gclone_aboutClicked);
gclone.moveLeftMouseUp += new MouseEventHandler(gclone_moveLeftMouseUp);
}
您可以通过在窗体的“Load
”事件中调用“setLocation
”方法来在应用程序启动时定位窗体。
private void Form1_Load(object sender, EventArgs e)
{
/*==============================================
* set the Windows start location
* ============================================= */
gclone.setLocation(Properties.Settings.Default.locationX,
Properties.Settings.Default.locationY);
}
弹出侧边菜单
通过处理主窗体上的“MouseEnter
”和“MouseLeave
”事件来显示和隐藏弹出侧边菜单。
private void Form1_MouseEnter(object sender, EventArgs e)
{
gclone.showMenu();
}
private void Form1_MouseLeave(object sender, EventArgs e)
{
if (!this.DesktopBounds.Contains(Cursor.Position))
gclone.hideMenu();
}
设置和关于对话框
“设置”和“关于”对话框的处理方式相同。首先创建您的窗体。然后,在您窗体的构造函数中声明的单击事件处理程序中,创建您的新对话框的实例。将对话框的“StartPosition
”设置为“Manual
”。调用 `gadgetClone` 的方法“minimizeForm
”以创建主窗口的缩略图。使用方法“settingsLocation
”来定位对话框。最后,显示对话框。
在对话框结束之后,调用“maximizeForm
”以恢复原始窗口。
private void gclone_settingsClicked(object sender, EventArgs e)
{
FormSettings dialog = new FormSettings();
dialog.StartPosition = FormStartPosition.Manual;
/*==============================================
* Minimize the main form and
* position the Settings Dialog
* ============================================= */
gclone.minimizeForm(dialog.Width, dialog.Height, false);
dialog.Location = gclone.settingsLocation(dialog.Width);
if (dialog.ShowDialog() == DialogResult.OK)
{
// TODO:
}
/*==============================================
* Restore the main form
* ============================================= */
gclone.maximizeForm(false);
}
浮出层
弹出窗口的显示方式类似。但是,排除了“minimizeForm
”和“maximizeForm
”方法。
private void buttonFlyout_Click(object sender, EventArgs e)
{
FormFlyout dialog = new FormFlyout();
dialog.StartPosition = FormStartPosition.Manual;
dialog.Location = gclone.flyoutLocation(dialog.Width);
dialog.ShowDialog();
}
就是这样!
关注点
这仅仅是开始。我邀请每个人随意更进一步,例如“备用尺寸”和“背景阴影”,或者可能实现 WPF 的适配。
历史
- 2010年4月4日:初始发布