0

読み込みオーバーレイとして機能するカスタム コントロールをセットアップしました。オーバーレイは、画像を表示するためのピクチャ ボックスを含むフォームです。

オーバーレイが所定の位置に配置され、それを呼び出すメイン フォームの前に表示されると、見栄えがよくなります。ただし、ユーザーがフォームを移動したりサイズを変更したりすると、フォームはメイン フォームの後ろに移動します。

メイン フォームが移動またはサイズ変更されている場合、オーバーレイ フォームは問題なく移動およびサイズ変更されますが、サイズ変更または移動が完了すると、フォームはメイン フォームの後ろに移動します。TopMost を使用せずにオーバーレイ フォームをトップに戻すにはどうすればよいですか?

を使用してメインフォームから以下のコードを呼び出します

LoadingControl p = new LoadingControl(dataGridView1, this);
p.Show();

そしてオーバーレイフォーム:

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class LoadingControl : Form
{
    private Color BackgroundColour = Color.Black;
    private double BackgroundOpacity = 0.50;
    private Image LoadingImage = APPNAME.Properties.Resources.loading_120x128;
    private Form Mainform;
    private Control MainControl;

    public LoadingControl(Control parent, Form frm)
    {
        MainControl = parent;
        Mainform = frm;
        SetupForm();

        Size = parent.ClientSize;
        Location = parent.PointToScreen(Point.Empty);

        Mainform.Move += AdjustPosition;
        MainControl.SizeChanged += AdjustPosition;
    }
    private void SetupForm()
    {
        FormBorderStyle = FormBorderStyle.None;
        BackColor = BackgroundColour;
        Opacity = BackgroundOpacity;//0.50;
        ShowInTaskbar = false;
        StartPosition = FormStartPosition.Manual;

        PictureBox pbox = new PictureBox {Image = LoadingImage, Parent = this};
        pbox.Width = pbox.Image.Width;
        pbox.Height = pbox.Image.Height;
        pbox.Left = (Width/2) - (pbox.Width/2);
        pbox.Top = (Height/2) - (pbox.Height/2)-10;
        pbox.Anchor = AnchorStyles.None;
        Controls.Add(pbox);
    }

    public void SetLoadingImage(Image img)
    {
        LoadingImage = img;
    }

    public void SetBackgroundColour(Color col)
    {
        BackgroundColour = col;
    }

    public void SetOpacity(double Opa)
    {
        BackgroundOpacity = Opa;
    }

    private void AdjustPosition(object sender, EventArgs e)
    {
        //TopMost = true;
        BringToFront();

        ClientSize = MainControl.ClientSize;
        Location = MainControl.PointToScreen(Point.Empty);
        //Mainform.Activate();      
        //TopMost = false;
        BringToFront();
        Focus();
        //MakeTopMost(this);
    }
}
4

1 に答える 1

1

何回呼び出しBringToFront()ても、フォームがアクティブなフォームの上に移動することはありません。BringToFront()コントロールをトップレベル コントロールにせず、Paint イベントを発生させません。

それを修正する方法が多すぎます。IMO の最善の方法は、ローディング コントロールをメイン フォームの子にすることです。それらを別々にして、移動またはサイズ変更のたびにコントロールを手動で配置する必要があります。

もう 1 つの方法は、コントロール ウィンドウの z オーダーを変更し、移動、サイズ変更、または最大化/最小化イベントが発生するたびにアクティブにすることです。

これは、少しの p-invokes で実現できます。

public void FocusForm()
{
    // force window to have focus
    uint foreThread = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
    uint appThread = GetCurrentThreadId();
    const uint SW_SHOW = 5;
    if (foreThread != appThread)
    {
        AttachThreadInput(foreThread, appThread, true);
        BringWindowToTop(this.Handle);
        ShowWindow(this.Handle, SW_SHOW);
        AttachThreadInput(foreThread, appThread, false);
    }
    else
    {
        BringWindowToTop(this.Handle);
        ShowWindow(this.Handle, SW_SHOW);
    }
    this.Activate();
}

[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();

[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll")]
static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

[DllImport("user32.dll", SetLastError = true)]
static extern bool BringWindowToTop(IntPtr hWnd);

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);

これを使用して、開始時にメインウィンドウが一番上になるように設定します。これActivate()により、最後に呼び出しを失いたい場合があります。

これはうまくいくかもしれませんが[移動とサイズ変更については完全にはテストしていません]、コードを修正して、ローディング コントロール フォームをメイン フォームの子として配置することをお勧めします。

編集:

透明なコントロールが必要な場合は、この SO question に対する受け入れられた回答を確認できます。それが私のコードであるという誤った主張をしたくないので、ここにコードを投稿することはできません.

于 2015-02-01T11:06:37.730 に答える