Windows 窗体 - MdiClient 滚动条未按预期自动显示

发布于 2024-08-05 08:25:58 字数 3519 浏览 7 评论 0原文

我正在用 C# 编写一个 Windows 窗体应用程序,可以启动一些 Windows 实用程序(例如 CMD 提示符、注册表编辑器、事件查看器等)并将其放置在主窗体上的 MdiClient 控件中。

除了当子窗口超出 MdiClient 边框时 MdiClient 控件中的滚动条不会自动出现之外,一切都运行良好。如果子窗口是窗口窗体,那么我知道 MdiClient 的滚动条会按预期自动显示。我尝试了很多事情,包括一些复杂的解决方法......我开始认为一定有一些我完全忽略的事情。

我在下面附加了一些示例代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;

namespace MdiClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            System.Windows.Forms.MdiClient mdiClient = new System.Windows.Forms.MdiClient();
            mdiClient.Dock = DockStyle.Fill;
            mdiClient.BackColor = Color.WhiteSmoke;
            this.Controls.Add(mdiClient);

            int processID = StartCMD();
            AddToMDIClient(processID, mdiClient.Handle);
        }

        private int StartCMD()
        {
            int processID = -1;

            using (Process process = new Process())
            {
                ProcessStartInfo startInfo = process.StartInfo;
                startInfo.FileName = "cmd.exe";

                try
                {
                    process.Start();
                    processID = process.Id;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }

            return processID;
        }
        private void AddToMDIClient(int processID, IntPtr mdiClientHandle)
        {
            try
            {
                Process process = Process.GetProcessById(processID);

                int numberOfAttempts = 0;
                while (string.IsNullOrEmpty(process.MainWindowTitle) && numberOfAttempts < 30)//max of 3 seconds
                {
                    Thread.Sleep(100);
                    process.Refresh();

                    numberOfAttempts++;
                }

                if (!string.IsNullOrEmpty(process.MainWindowTitle))
                {
                    SetWindowPos(process.MainWindowHandle, HWND_TOPMOST, 1, 1, 0, 0, TOPMOST_FLAGS);

                    SetParent(process.MainWindowHandle, mdiClientHandle);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
            int Y, int cx, int cy, uint uFlags);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
        public const UInt32 TOPMOST_FLAGS = /*SWP_NOMOVE | */SWP_NOSIZE;

        public const UInt32 SWP_NOSIZE = 0x0001;
    }
}

下面的屏幕截图显示,当移动 CMD 窗口使其边框位于 MdiClient 边框之外时,没有滚动条:

请参阅此链接以获取图像: http://picasaweb.google.com/lh/photo/75rMVJMCWRg_s_DFF6LmNg?authkey=Gv1sRgCI KRlsu8xuDh8AE&壮举=directlink

任何帮助将不胜感激!

谢谢, 阴凉

I'm writing a windows forms application in C# whereby some windows utilities can be launched (e.g. CMD prompt, Registry editor, Events Viewer etc) and placed in an MdiClient control on the main form.

Everything is working great except that the scroll bars in the MdiClient control aren't automatically appearing when a child window falls beyond the MdiClient's borders. If the child windows were windows forms then I know that the MdiClient's scroll bars would automatically appear as expected. I've tried many things, including some complex workarounds.. and i'm beginning to think there must be something i'm completely overlooking.

I have attached some sample code below:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;

namespace MdiClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            System.Windows.Forms.MdiClient mdiClient = new System.Windows.Forms.MdiClient();
            mdiClient.Dock = DockStyle.Fill;
            mdiClient.BackColor = Color.WhiteSmoke;
            this.Controls.Add(mdiClient);

            int processID = StartCMD();
            AddToMDIClient(processID, mdiClient.Handle);
        }

        private int StartCMD()
        {
            int processID = -1;

            using (Process process = new Process())
            {
                ProcessStartInfo startInfo = process.StartInfo;
                startInfo.FileName = "cmd.exe";

                try
                {
                    process.Start();
                    processID = process.Id;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }

            return processID;
        }
        private void AddToMDIClient(int processID, IntPtr mdiClientHandle)
        {
            try
            {
                Process process = Process.GetProcessById(processID);

                int numberOfAttempts = 0;
                while (string.IsNullOrEmpty(process.MainWindowTitle) && numberOfAttempts < 30)//max of 3 seconds
                {
                    Thread.Sleep(100);
                    process.Refresh();

                    numberOfAttempts++;
                }

                if (!string.IsNullOrEmpty(process.MainWindowTitle))
                {
                    SetWindowPos(process.MainWindowHandle, HWND_TOPMOST, 1, 1, 0, 0, TOPMOST_FLAGS);

                    SetParent(process.MainWindowHandle, mdiClientHandle);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
            int Y, int cx, int cy, uint uFlags);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
        public const UInt32 TOPMOST_FLAGS = /*SWP_NOMOVE | */SWP_NOSIZE;

        public const UInt32 SWP_NOSIZE = 0x0001;
    }
}

The screenshot below shows that when the CMD window is moved so its borders are outside the borders of the MdiClient there are no scroll bars:

Please see this link for the image: http://picasaweb.google.com/lh/photo/75rMVJMCWRg_s_DFF6LmNg?authkey=Gv1sRgCIKRlsu8xuDh8AE&feat=directlink

Any help would be much appreciated!

Thanks,
Shady

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

爱的故事 2024-08-12 08:25:58

如果没有屏幕截图,很难说,但我认为创建 MDIParanet 的方式太复杂了。

private void Form1_Load(object sender, EventArgs e)
    {
       // System.Windows.Forms.MdiClient mdiClient = new System.Windows.Forms.MdiClient();
       //  mdiClient.Dock = DockStyle.Fill;
       // mdiClient.BackColor = Color.WhiteSmoke;
       // this.Controls.Add(mdiClient);

       this.IsMdiContainer = true;

        int processID = StartCMD();
        AddToMDIClient(processID, mdiClient.Handle);
    }

如果需要Client,可以从Controls中过滤掉。

另一个问题可能是将 MDIChild 设置为 TOP_MOST,我认为这不是一个好的组合。

Without the screenshot it is hard to say, but I think the way you create the MDIParanet is way too complicated.

private void Form1_Load(object sender, EventArgs e)
    {
       // System.Windows.Forms.MdiClient mdiClient = new System.Windows.Forms.MdiClient();
       //  mdiClient.Dock = DockStyle.Fill;
       // mdiClient.BackColor = Color.WhiteSmoke;
       // this.Controls.Add(mdiClient);

       this.IsMdiContainer = true;

        int processID = StartCMD();
        AddToMDIClient(processID, mdiClient.Handle);
    }

If you need the Client, you can filter it from Controls.

Another problem might be setting a MDIChild as TOP_MOST, I don't think that's a good combination.

难理解 2024-08-12 08:25:58

我一直在做一些测试,只要我在表单属性中设置 Autoscroll = true ,它就可以正常工作。

另外,我注意到,如果您放大表单并将命令窗口移动到右下角,它不会显示滚动条,只有当您最小化表单超过命令窗口时才会显示滚动条(请参见下面的屏幕截图)

屏幕截图 1
http://picasaweb.google.com/lh/photo/rfwm- S8y06Fl3HFNshgj3g?feat=directlink

截图 2
http://picasaweb.google.com/lh/photo/y6qkN9Jj19vDGFNkTuL4FQ?feat= directlink

另外,你能不能在Form的属性上设置AutoScrollMinSize,这样你的表单中总是会有滚动条小于设置的尺寸

希望对

Josh有帮助

I have been doing some testing and it work ok for me was long as I have Autoscroll = true in the forms properties.

Also, I noticed if you enlarge the form and move the command window to say the bottom right it will not show the scroll bars, it will only when you minimize the form past the command windows (see screenshots below)

Screenshot 1
http://picasaweb.google.com/lh/photo/rfwm-S8y06Fl3HFNshgj3g?feat=directlink

Screenshot 2
http://picasaweb.google.com/lh/photo/y6qkN9Jj19vDGFNkTuL4FQ?feat=directlink

Also, can you set on the Form's properties AutoScrollMinSize, so that you always have scroll bars in the form is smaller than the size set

Hope that helps

Josh

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文