Наложение формы, показываемое за формой при перемещении и изменении размера
Я настроил пользовательский элемент управления, который действует как наложение загрузки, наложение - это форма с картинкой для показа изображения.
Когда наложение показывает, что оно находится в позиции и находится перед основной формой, вызывающей его, это выглядит великолепно. Однако, когда пользователь перемещает форму или изменяет ее размер, форма возвращается к основной форме.
Наложенная форма перемещается и изменяет размеры без проблем, когда основная форма перемещается или изменяет размеры, однако после того, как она закончила изменять размер или перемещать форму, она выходит за основную форму. Как я могу вернуть оверлейную форму обратно наверх, не используя 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);
}
}
1 ответ
Независимо от того, сколько раз вы звоните BringToFront()
она не будет перемещать вашу форму поверх активной. BringToFront()
не делает элемент управления элементом верхнего уровня и не вызывает событие Paint.
Есть слишком много способов исправить это. Лучший способ IMO - сделать ваш элемент управления загрузкой дочерним по отношению к основной форме, а не разделять их, и вам придется вручную размещать элемент управления после каждого перемещения или изменения размера.
Другой способ, который можно сделать, это изменить z-порядок окна управления и активировать его после каждого события перемещения, изменения размера или максимизации / минимизации.
Это может быть достигнуто с небольшим количеством p-вызовов:
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. Я не могу опубликовать код здесь, так как я не хочу ложно утверждать, что это мой код.