C# 示例代码/文章:扩展 C# (.NET) 中 GDI+ 的功能 - 第 III 部分





2.00/5 (2投票s)
一篇关于 C# 示例代码/文章扩展 C# (.NET) 中 GDI+ 功能的文章

引言
在这里,作为我上一篇文章的延续,我介绍了另一种选择图像部分的方法。 就像我上一篇文章中的方法 2一样,用户不必担心选择矩形的调整大小/移动问题,因为这些将由选择窗口(也就是 Win32 窗口)处理。
这里采用的方法是,我在子窗体的窗口过程中捕获WM_EXITSIZEMOVE消息。 之前在主窗体中,我重写了OnLoad(…)
方法并创建了另一个窗体,我们称之为类似子窗体的窗体(因为它几乎像主窗体的子窗体一样运行)并将它的所有者设置为我的主窗体。 见图 1。
protected override void OnLoad(EventArgs e)
{
chFrm = new ChildForm();
chFrm.Owner = this;
chFrm.Show();
chFrm.Location = new Point(Location.X + 50, Location.Y + 50);
base.OnLoad(e);
}
现在类似子窗体的当前父窗体是桌面窗口,因此它变得透明(透明性在其客户区中体现),因为它现在等同于一个弹出窗口。 当用户尝试移动类似子窗体的窗体时,我快速做了两件事
- 将其父窗体从桌面窗口更改为主窗体
- 通过
SetWindowLong(…)
Win32 API 删除其WS_EX_LAYERED
属性
这确保了类似子窗体的窗体永远不会离开主窗体。 当用户停止上述操作时,我只需要反向操作即可。
注意:为了获取桌面窗口的句柄,我使用 Win32 API,如下所示,通过pInvoke
。
[DllImport("user32.dll")]
static extern IntPtr GetDesktopWindow();
由于我们知道如果一个窗体成为子窗体,我们不能在其上应用SetLayeredWindowAttributes (…)
API。 那么子窗体是如何仍然变得透明的呢? 输入子窗体的WM_EXITSIZEMOVE消息。 在退出移动或调整大小的模式循环后,WM_EXITSIZEMOVE
消息会被发送到窗口一次。 所以要像上面说的那样反向操作,我快速再做两件事
- 切换子窗体的父窗体;从主窗体到桌面窗口
- 切换其分层属性,即我将
WS_EX_LAYERED
属性添加回子窗体
以上两件事帮助子窗体重获透明性,从而使用户能够看到其客户区。
下面显示了 Win32-API 设置透明度,即
[DllImport ("user32.dll")]
public static extern long SetLayeredWindowAttributes
(IntPtr Handle, int Clr, byte transparency, int clrkey);
第四个参数int clrKey
是键,在调用此 API 时,我为clrKey
参数指定一种特定颜色,然后我用相同的颜色绘制类似子窗体的窗体。 这将在窗体的客户区创建一个孔。
注意:每当窗体更改其父窗体时,它也会根据其当前父窗体重新定位自身,基于其在WM_NCLBUTTONDOWN
和WM_EXITSIZEMOVE
消息中的先前相对位置更改其位置,这可以防止这种不希望的位置更改。
历史
- 2008 年 7 月 11 日:初始版本