【问题标题】:How do you prevent a windows from being moved?如何防止窗户被移动?
【发布时间】:2010-10-28 19:32:21
【问题描述】:

我将如何阻止表单被移动。我将表单边框样式设置为 FixedSingle 并希望保持这种方式,因为它在 vista 中看起来不错:)

【问题讨论】:

  • 被感动是什么意思?您的意思是无法将其拖动到桌面上的其他位置?
  • 如果用户在右下角有其他小部件,比如 vista 侧边栏,该怎么办?你真的想规定你的窗户必须放在哪里吗?这绝不是用户友好的,我个人不会接受这样的限制。
  • 如果表格被移动,是不是可以重新定位到它的初始位置?

标签: c# .net winforms user-interface


【解决方案1】:

看看这个link。您可能对选项 #3 感兴趣。它将要求您包装一些本机代码,但应该可以工作。链接底部还有一条评论,显示了一种更简单的方法。摘自评论(不能归功于它,但我会为您节省一些搜索):

protected override void WndProc(ref Message message)
{
    const int WM_SYSCOMMAND = 0x0112;
    const int SC_MOVE = 0xF010;

    switch(message.Msg)
    {
        case WM_SYSCOMMAND:
           int command = message.WParam.ToInt32() & 0xfff0;
           if (command == SC_MOVE)
              return;
           break;
    }

    base.WndProc(ref message);
}

【讨论】:

  • 感谢这完美的工作。还阅读了该网站。必须更多地研究 WinAPI。
  • 我怎样才能让它再次移动?
  • 你必须有某种标志来决定是否运行 switch 语句中的代码(它只是检查窗口消息是否是移动窗口.. . 在这种情况下它返回并且什么都不做)。
【解决方案2】:

您可以将表单的FormBorderStyle 属性设置为无

this.FormBorderStyle=System.Windows.Forms.FormBorderStyle.None

【讨论】:

    【解决方案3】:

    我发现这可以阻止表单移动(在 c# 中)

    protected override void WndProc(ref Message m)
            {
                const int WM_SYSCOMMAND = 0x0112;
                const int SC_MOVE = 0xF010;
    
                switch (m.Msg)
                {
                    case WM_SYSCOMMAND:
                        int command = m.WParam.ToInt32() & 0xfff0;
                        if (command == SC_MOVE)
                            return;
                        break;
                }
                base.WndProc(ref m);
            }
    

    Found here

    【讨论】:

    • 在什么情况下我应该写这个?
    • 您必须覆盖 WndProc 以使您不希望移动的表单。输入覆盖和空格,你会得到一个列表,你会在其中找到上面提到的方法
    • @V4Vendetta 可能是因为您的答案与两年前发布的已接受答案完全相同......我也不明白(不是我的反对意见)
    • @Knickedi 这可能是类似问题与答案合并的情况,因此您会看到时间线存在巨大差异。
    【解决方案4】:

    尝试覆盖 WndProc:

    protected override void WndProc(ref Message m)
    {
       const int WM_NCLBUTTONDOWN = 161;
       const int WM_SYSCOMMAND = 274;
       const int HTCAPTION = 2;
       const int SC_MOVE = 61456;
    
       if ((m.Msg == WM_SYSCOMMAND) && (m.WParam.ToInt32() == SC_MOVE))
       {
           return;
       }
    
       if ((m.Msg == WM_NCLBUTTONDOWN) && (m.WParam.ToInt32() == HTCAPTION))
       {
           return;
       }
    
       base.WndProc(ref m);
    }
    

    【讨论】:

    • 我怎样才能让它再次移动?
    【解决方案5】:

    这不是很漂亮(当您尝试移动表单时会出现一些闪烁),但您可以使用 LocationChanged 属性将表单保持在您想要的位置:

    private Point _desiredLocation;
    // assign the _desiredLocation variable with the form location at some
    // point in the code where you know that the form is in the "correct" position
    
    
    private void Form_LocationChanged(object sender, EventArgs e)
    {
        if (this.Location != _desiredLocation)
        {
            this.Location = _desiredLocation;
        }
    }
    

    出于好奇;你为什么要这样做?

    【讨论】:

    • 是的,我认为这并不容易:(我想要这个的原因是因为我想让一个表单像菜单一样出现在屏幕的右下角。所以你可以选择文件等
    • 我会怎么做 - 不看我不认为有一个属性可以在 .NET 中设置来做到这一点,所以这是你最好的选择。
    【解决方案6】:

    在 Windows 中,WS_CAPTION 样式是允许用鼠标移动窗口的非客户区。因此,最简单的方法是从窗口中删除此样式。

    但是,如果您需要一个标题并且仍然实现您想要的,那么下一个样式将是捕获 WM_NCHITTEST 消息并检查 HTCAPTION。如果代码是 HTCAPTION,则返回 NTNOWHERE。这将阻止默认窗口过程执行默认移动窗口的事情。

    【讨论】:

    • 感谢您的回复。我大约一个月前才开始桌面编程,所以我不知道如何实现你所说的任何内容。对不起。我觉得很无知:(
    【解决方案7】:

    让您的表单不可移动不是一个好习惯。如果我是你,我会考虑的。
    无论如何,您可以通过覆盖 WinProc 以禁用系统菜单中的 [Move] 菜单项来做到这一点。

    [DllImport("user32.dll")]
    private static extern Int32 EnableMenuItem ( System.IntPtr hMenu , Int32uIDEnableItem, Int32 uEnable);  
    private const Int32 HTCAPTION = 0×00000002;  
    private const Int32 MF_BYCOMMAND =0×00000000;  
    private const Int32 MF_ENABLED =0×00000000;  
    private const Int32 MF_GRAYED =0×00000001;  
    private const Int32 MF_DISABLED =0×00000002; 
    private const Int32 SC_MOVE = 0xF010; 
    private const Int32 WM_NCLBUTTONDOWN = 0xA1;
    private const Int32 WM_SYSCOMMAND = 0×112;
    private const Int32 WM_INITMENUPOPUP = 0×117;
    
    protected override void WndProc(ref System.Windows.Forms.Message m )
    {
    if (m.Msg == WM_INITMENUPOPUP)
    {
        //handles popup of system menu
        if ((m.LParam.ToInt32() / 65536) != 0) // 'divide by 65536 to get hiword
        {
            Int32 AbleFlags = MF_ENABLED;
            if (!Moveable)
            {
                AbleFlags = MF_DISABLED | MF_GRAYED; // disable the move
            }
            EnableMenuItem(m.WParam, SC_MOVE, MF_BYCOMMAND | AbleFlags);
        }
    }
    if (!Moveable)
    {
        if (m.Msg == WM_NCLBUTTONDOWN) //cancels the drag this is IMP
        {
            if (m.WParam.ToInt32() == HTCAPTION) return;
        }
        if (m.Msg == WM_SYSCOMMAND) // Cancels any clicks on move menu
        {
            if ((m.WParam.ToInt32() & 0xFFF0) == SC_MOVE) return;
        }
    }
    base.WndProc(ref m);
    }  
    

    此外,您可以处理表单的OnMove 事件。但我认为这会导致一些闪烁:

    private void Form1_Move(object sender, EventArgs e)
    {
        this.Location = defaultLocation;
    }
    

    【讨论】:

      【解决方案8】:
      1. 转到表单事件->位置已更改

      编写如下代码

      Location = new Point(this.Width,this.Height);
      

      【讨论】:

      • 不适合我!我认为您应该先保存顶部和左侧位置的值,然后: Location = new Point(LeftPosition,TopPosition);
      【解决方案9】:

      只需将FormBorderStyle 属性更改为None

      【讨论】:

      • 嗯,这就是我想要的。全屏用户界面。
      【解决方案10】:

      将表单属性 StartPostion 更改为手动。 然后,处理 LocationChanged 事件:

      private void frmMain_LocationChanged(object sender, EventArgs e)
      {
      Location = new Point(0, 0);
      }
      

      【讨论】:

        【解决方案11】:

        我会质疑您是否需要使表格不可移动。这听起来不太好。您当然可以在窗口关闭时保存窗口的位置,然后将窗口重新打开到该位置。这让用户可以控制窗口的位置。

        【讨论】:

        • 嗯...这个程序的重点是不要移动它,哈哈。
        【解决方案12】:

        您可以订阅Form.Move 事件并从中重新定位。

        【讨论】:

        • 是的,我试过了,但是当我尝试将其移动到新位置时,表单开始闪烁很多。
        • @Failed_Noob - 编辑您的问题,发布代码,也许有人可以提出修复建议。
        【解决方案13】:

        只需将 formlocation_changed 事件的位置重置为原来的位置,即将 Form.Location 在移动之前设置为变量,当用户尝试移动它时,它将返回到您设置的变量位置。

        【讨论】:

          【解决方案14】:

          私有子 MyFormLock() Me.Location = 新点 (0, 0) 结束子

          Private Sub SearchSDR_LocationChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.LocationChanged
              Call MyFormLock()
          End Sub
          

          【讨论】:

            【解决方案15】:

            你可以试试:

            this.Locked = true;
            

            【讨论】:

            • 有很多比这个更好的答案!如果你要添加一个完全不同的答案,至少解释一下!
            猜你喜欢
            • 2017-05-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多