У меня есть приложение winforms на C #, которое запускает макрос в другой программе. Другая программа будет постоянно выскакивать из окон и в целом заставлять вещи выглядеть, если не сказать точнее, сумасшедшими. Я хочу реализовать кнопку отмены, которая остановит процесс, но я не могу заставить окно оставаться наверху. Как мне это сделать на C #?
Изменить: я пробовал TopMost = true; , но другая программа продолжает открывать свои окна поверх. Есть ли способ отправлять мое окно наверх каждые n миллисекунд?
Изменить: Я решил это, добавив значок на панели задач, который отменит процесс, дважды щелкнув по нему. Значок на панели задач не закрывается. Спасибо всем, кто откликнулся. Прочитал статью о том, почему нет окна "супер-поверх" ... по логике не работает.
Ответы:
Form.TopMost
будет работать, если другая программа не создает самые верхние окна.Невозможно создать окно, которое не закрывается новыми самыми верхними окнами другого процесса. Раймонд Чен объяснил почему.
источник
Form.ActiveForm.TopMost
Я пытался сделать свое приложение WinForms «Всегда наверху», но установка «TopMost» ничего не дала мне. Я знал, что это возможно, потому что WinAmp делает это (вместе с множеством других приложений).
Что я сделал, так это позвонил в "user32.dll". Я не сомневался в этом, и он отлично работает. Во всяком случае, это вариант.
Сначала импортируйте следующее пространство имен:
using System.Runtime.InteropServices;
Добавьте несколько переменных в объявление вашего класса:
private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); private const UInt32 SWP_NOSIZE = 0x0001; private const UInt32 SWP_NOMOVE = 0x0002; private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
Добавьте прототип для функции user32.dll:
[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
Затем в вашем коде (я добавил вызов в Form_Load ()) добавьте вызов:
SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
Надеюсь, это поможет. Справка
источник
Если под словом «сойти с ума» вы имеете в виду, что каждое окно продолжает отнимать фокус у другого, TopMost не решит проблему.
Вместо этого попробуйте:
Это покажет «дочернюю» форму, не отвлекая внимание. Дочерняя форма также останется поверх своей родительской, даже если родительская форма активирована или сфокусирована. Этот код работает легко, только если вы создали экземпляр дочерней формы из формы владельца. В противном случае вам, возможно, придется установить владельца с помощью API.
источник
CalledForm.Owner
на себя (CalledForm
) вызоветSystem.ArgumentException
: «Была сделана циклическая ссылка на элемент управления. Элемент управления не может принадлежать самому себе ».Установить Form.TopMost
источник
У меня был кратковременный перерыв в 5 минут, и я забыл указать форму полностью следующим образом:
myformName.ActiveForm.TopMost = true;
Но на самом деле я хотел ЭТОГО!
this.TopMost = true;
источник
Установите для
.TopMost
свойства формы значение true.Вероятно, вы не захотите оставлять его так все время: установите его при запуске внешнего процесса и верните его обратно, когда он завершится.
источник
Я решил эту проблему, сделав значок в системном трее с возможностью отмены.
источник
Следующий код заставляет окно всегда оставаться наверху, а также делает его безрамочным.
using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace StayOnTop { public partial class Form1 : Form { private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); private const UInt32 SWP_NOSIZE = 0x0001; private const UInt32 SWP_NOMOVE = 0x0002; private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE; [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); public Form1() { InitializeComponent(); FormBorderStyle = FormBorderStyle.None; TopMost = true; } private void Form1_Load(object sender, EventArgs e) { SetWindowPos(this.Handle, HWND_TOPMOST, 100, 100, 300, 300, TOPMOST_FLAGS); } protected override void WndProc(ref Message m) { const int RESIZE_HANDLE_SIZE = 10; switch (m.Msg) { case 0x0084/*NCHITTEST*/ : base.WndProc(ref m); if ((int)m.Result == 0x01/*HTCLIENT*/) { Point screenPoint = new Point(m.LParam.ToInt32()); Point clientPoint = this.PointToClient(screenPoint); if (clientPoint.Y <= RESIZE_HANDLE_SIZE) { if (clientPoint.X <= RESIZE_HANDLE_SIZE) m.Result = (IntPtr)13/*HTTOPLEFT*/ ; else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE)) m.Result = (IntPtr)12/*HTTOP*/ ; else m.Result = (IntPtr)14/*HTTOPRIGHT*/ ; } else if (clientPoint.Y <= (Size.Height - RESIZE_HANDLE_SIZE)) { if (clientPoint.X <= RESIZE_HANDLE_SIZE) m.Result = (IntPtr)10/*HTLEFT*/ ; else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE)) m.Result = (IntPtr)2/*HTCAPTION*/ ; else m.Result = (IntPtr)11/*HTRIGHT*/ ; } else { if (clientPoint.X <= RESIZE_HANDLE_SIZE) m.Result = (IntPtr)16/*HTBOTTOMLEFT*/ ; else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE)) m.Result = (IntPtr)15/*HTBOTTOM*/ ; else m.Result = (IntPtr)17/*HTBOTTOMRIGHT*/ ; } } return; } base.WndProc(ref m); } protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.Style |= 0x20000; // <--- use 0x20000 return cp; } } } }
источник
Какое еще приложение вы пытаетесь скрыть от видимости? Вы исследовали другие способы достижения желаемого эффекта? Пожалуйста, сделайте это, прежде чем подвергать своих пользователей такому мошенническому поведению, которое вы описываете: то, что вы пытаетесь сделать, скорее похоже на то, что некоторые непослушные сайты делают с окнами браузера ...
По крайней мере, постарайтесь придерживаться правила наименьшего сюрприза . Пользователи ожидают, что смогут сами определять z-порядок большинства приложений. Вы не знаете, что для них наиболее важно, поэтому, если вы что-то измените, вам следует сосредоточиться на том, чтобы подталкивать другое приложение за всем, а не продвигать свое собственное.
Это, конечно, сложнее, поскольку в Windows нет особо сложного оконного менеджера. Напрашиваются два подхода:
источник
Почему бы не сделать вашу форму диалоговым окном:
источник
TopMost = true
заставила мою форму работать поверх всего, включая хром, хотя на самом деле это всего лишь окно настроек, и мне это нужно было поверх основной формы. Престижность вам, интернет-человек.Вот эквивалент SetForegroundWindow:
Я видел, как люди делали такие странные вещи, как:
this.TopMost = true; this.Focus(); this.BringToFront(); this.TopMost = false;
http://blog.jorgearimany.com/2010/10/win32-setforegroundwindow-equivalent-in.html
источник
this.Show(); this.Activate(); this.BringToFront();
Но этот ответ привел нас к этому решению. Благодарность!Я знаю, что это старый, но я не видел этого ответа.
В окне (xaml) добавьте:
Deactivated="Window_Deactivated"
В коде для Window_Deactivated:
private void Window_Deactivated(object sender, EventArgs e) { Window window = (Window)sender; window.Activate(); }
Так ваше окно останется наверху.
источник
Основываясь на ответе Clamum и комментарии Кевина Вуйломье о другом флаге, отвечающем за поведение, я сделал этот переключатель, который переключается между верхним и не верхним слоем нажатием кнопки.
private void button1_Click(object sender, EventArgs e) { if (on) { button1.Text = "yes on top"; IntPtr HwndTopmost = new IntPtr(-1); SetWindowPos(this.Handle, HwndTopmost, 0, 0, 0, 0, TopmostFlags); on = false; } else { button1.Text = "not on top"; IntPtr HwndTopmost = new IntPtr(-2); SetWindowPos(this.Handle, HwndTopmost, 0, 0, 0, 0, TopmostFlags); on = true; } }
источник