创建可以通过拖动背景区域中的任何位置来移动的非矩形表单

时间:2012-02-17 01:57:13

标签: c# .net windows winforms winapi

我想通过左键单击并按住背景区域来移动窗体窗口,就像我们通常使用标题栏一样。

然后我还想将我的应用程序的窗体窗口(即矩形窗口)更改为我自定义设计的图形窗口。我在许多其他应用程序中看到过这种类型的窗口,所以我相信它是可能的。

2 个答案:

答案 0 :(得分:5)

问题1:

要在拖动客户区时允许移动表单,您需要告诉窗口管理器将客户区区域视为标题栏(标题区域)。你在问题中建议类似的东西。

这可以在.NET中通过覆盖表单的WndProc method,回复WM_NCHITTEST消息,然后返回HTCAPTION来表明所有内容都应该作为标题(标题)栏,而不是默认的HTCLIENT,表示应将其视为表单的客户区。将以下代码添加到表单类:

private const int WM_NCHITTEST = 0x84;
private const int HTCLIENT = 0x1;
private const int HTCAPTION = 0x2;

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    if (m.Msg == WM_NCHITTEST)
    {
        // Convert HTCLIENT to HTCAPTION
        if (m.Result.ToInt32() == HTCLIENT)
        {
            m.Result = (IntPtr)HTCAPTION;
        }
    }
}

问题2:

您可以通过将表单的Region property设置为您选择的自定义Region来创建任意非矩形形状的表单。如果您有使用Photoshop等图形程序的经验,可以将其视为为表单设置“剪裁区域”:窗口管理器不会在您指定的范围之外绘制任何内容。这个Region描述的形状中的像素甚至可以是不连续的。

创建区域的最简单方法可能是使用GraphicsPath class,然后使用接受单个GraphicsPath对象的constructor for the Region class作为参数。

正如我假设您已经知道的那样,在第一个问题的情况下,您必须将FormBorderStyle property设置为None,以确保窗口管理器绘制的默认边框消失。

不幸的是,这些地区不能消除锯齿。有关这些限制的详细信息,请参阅Hans's answer to this question

最后,值得注意的是,后一种创建非矩形表单的方法可能会产生一些简直丑陋的用户界面,这些界面根本不会提高产品的可用性,如下所示:

Windows Media Player "alien head"

请谨慎使用这项技术,并做出良好的判断。如果有疑问,矩形实际上是一个非常好的窗户形状。

答案 1 :(得分:1)

这是一篇令人印象深刻的CodeProject文章的链接,它将回答您的两个问题:An Alpha Channel Composited Windows Form with Designer Support。该实现使用前后窗组合。 它使用WS_EX_LAYERED显示基于位图的窗口,并将鼠标事件挂钩到主窗体,以便允许拖动它。

有一点看起来有点像窗户被拖动时 - 前窗和后窗的移动之间有一个小的延迟,使它们看起来像是在互相追逐。

下一篇CodeProject文章展示了一种通过使用DeferWindowPos来解决该问题的方法:Alpha Blended Windows Forms

祝你好运!