一个 C# 示例代码/文章,扩展 C# (.NET) 中 GDI+ 的功能 - 第二部分
本文是上一篇文章的延续,我在其中介绍了另外两种实现相同功能的方法

引言
这里,作为 我之前的文章 的延续,我将介绍另外两种实现相同功能的方法。
方法 1 项目名称:ReversePaint
正如一位读者建议的那样,我们的确有等同于 DrawDragRect(…)
的方法,即 public static void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
,但像调整普通窗口大小那样调整选择矩形大小以及拖放等功能确实需要与我之前的示例代码中类似的代码。 作为概念验证,我在 ReversePaint
下载中提供了示例代码。 请参见函数 public void DrawDragRect()
,了解唯一的重大区别。 CDrawDragRect
可以派生自 Panel
和 Form
,具体取决于编码人员的选择。
方法 2 项目名称:WindowPosChanging
在这里,我采取了一种全新的方法。 正如你所看到的,调整大小、拖动和放置选择矩形需要像普通窗口一样运行,那么为什么不使用普通窗口来做同样的事情呢? 这样,Windows 将自动处理调整大小和其他功能。 为此,窗口(实际上将是一个窗体,让我们称之为 childLike
窗体;参见下图)必须有一个孔,以便用户可以透过它看到图像的一部分。
有一个专门为此的 Win32-API,即
[DllImport("user32.dll")]
public static extern long SetLayeredWindowAttributes
(IntPtr Handle, int Clr, byte transparency, int clrkey);
第四个参数 int clrKey
是键。 调用此 API 时,我为 clrKey
参数指定一种特定的颜色,并且进一步使用相同的颜色绘制 childLike
窗体。 这将在窗体的客户区创建一个孔。
但它有一个缺点 - 它不会在子窗口(窗体)中创建一个孔,此 API 仅在弹出窗口中有效。
现在我们的 childLike
窗体必须是一个弹出窗体,而不是 MDI 子窗体或子窗口。 如果它是弹出窗口,它将移出我们托管图像的主窗口。 因此,窗体的移动需要限制在主窗体中。 这是通过在窗体的 WndProc(ref Message m)
函数中捕获 WM_WINDOWPOSCHANGING
消息来实现的。
在处理此消息时,我只是确保 WINDOWPOS winPos
(我通过 m.Lparam
获取)不会离开主窗体。
消息的处理方式分为两部分
childLike
窗体不能拖到Mainform
之外。- 当移动主窗体时,我只需要为
childLike
窗体触发一个WM_MOVE
消息,这可以确保childLike
窗体不会超出主窗体。 看一下下面的代码
protected override void OnMove(EventArgs e)
{
if (chFrm != null)
{
MoveWindow(chFrm.Handle, chFrm.Location.X, chFrm.Location.Y,
chFrm.Size.Width, chFrm.Size.Height, true);
MinimumSize = new Size(chFrm.Size.Width + 100, chFrm.Size.Height);
}
base.OnMove(e);
}
请注意,在 OnMove(...)
函数中进行的 MoveWindow(...)
调用是虚拟的。
这是一种免费的礼物,只需在桌面上移动主窗体,看看 childLike
窗体如何忠实地跟随它。
这就是调整大小功能的全部内容,现在是拖放功能。
由于窗体上有一个孔,用户可以拖放 childLike
窗体,如下图所示

这是通过重写 Mouse-move 函数并在其中调用 BestSelfMoveOnMoveNotRequired ()
函数来实现的。 此函数执行 childLike
窗体的移动。
历史
- 2008 年 6 月 10 日:初始版本
- 2008 年 7 月 2 日:文章更新