Nice programing

.Net에서 창을 항상 맨 위에 유지하는 방법은 무엇입니까?

nicepro 2020. 9. 25. 23:37
반응형

.Net에서 창을 항상 맨 위에 유지하는 방법은 무엇입니까?


다른 프로그램에서 매크로를 실행하는 C # winforms 앱이 있습니다. 다른 프로그램은 계속해서 창을 띄우고 일반적으로 더 나은 단어가 없기 때문에 상황을 미치게 만듭니다. 프로세스 실행을 중지하는 취소 버튼을 구현하고 싶지만 창을 맨 위에 유지하지 못하는 것 같습니다. C #에서 어떻게합니까?

편집 : 나는 TopMost = true를 시도했습니다; ,하지만 다른 프로그램은 계속해서 상단에 자체 창을 표시합니다. n 밀리 초마다 내 창을 맨 위로 보내는 방법이 있습니까?

편집 :이 문제를 해결 한 방법은 두 번 클릭하여 프로세스를 취소하는 시스템 트레이 아이콘을 추가하는 것입니다. 시스템 트레이 아이콘이 가려지지 않습니다. 응답 해 주신 모든 분들께 감사드립니다. 왜 '슈퍼 온탑'창이 없는지에 대한 기사를 읽었습니다. 논리적으로 작동하지 않습니다.


Form.TopMost 다른 프로그램이 최상위 창을 생성하지 않는 한 작동합니다.

다른 프로세스의 새 최상위 창으로 덮이지 않는 창을 만들 수있는 방법이 없습니다. Raymond Chen은 이유를 설명했습니다 .


WinForms 응용 프로그램을 "Always on Top"으로 만들려고했지만 "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는 문제를 해결하지 못할 것입니다.

대신 다음을 시도하십시오.

CalledForm.Owner = CallerForm;
CalledForm.Show();

이것은 초점을 훔치지 않고 '아이'형태를 ​​보여줄 것입니다. 부모가 활성화되었거나 포커스가있는 경우에도 자식 양식은 부모 위에 유지됩니다. 이 코드는 소유자 양식 내에서 하위 양식의 인스턴스를 만든 경우에만 쉽게 작동합니다. 그렇지 않으면 API를 사용하여 소유자를 설정해야 할 수 있습니다.


Form.TopMost 설정


양식의 .TopMost속성을 true로 설정 합니다.

항상 이런 식으로 남겨두고 싶지는 않을 것입니다. 외부 프로세스가 시작될 때 설정하고 완료되면 다시 넣으십시오.


나는 순간적으로 5 분의 경과가 있었고 다음과 같이 전체 양식을 지정하는 것을 잊었습니다.

  myformName.ActiveForm.TopMost = true;

그러나 내가 정말로 원했던 것은 이것이었다!

  this.TopMost = true;

The way i solved this was by making a system tray icon that had a cancel option.


The following code makes the window always stay on top as well as make it frameless.

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;
            }
        }
    }
}

What is the other application you are trying to suppress the visibility of? Have you investigated other ways of achieving your desired effect? Please do so before subjecting your users to such rogue behaviour as you are describing: what you are trying to do sound rather like what certain naughty sites do with browser windows...

At least try to adhere to the rule of Least Surprise. Users expect to be able to determine the z-order of most applications themselves. You don't know what is most important to them, so if you change anything, you should focus on pushing the other application behind everything rather than promoting your own.

This is of course trickier, since Windows doesn't have a particularly sophisticated window manager. Two approaches suggest themselves:

  1. enumerating top-level windows and checking which process they belong to, dropping their z-order if so. (I'm not sure if there are framework methods for these WinAPI functions.)
  2. Fiddling with child process permissions to prevent it from accessing the desktop... but I wouldn't try this until the othe approach failed, as the child process might end up in a zombie state while requiring user interaction.

Why not making your form a dialogue box:

myForm.ShowDialog();

Here is the SetForegroundWindow equivalent:

form.Activate();

I have seen people doing weird things like:

this.TopMost = true;
this.Focus();
this.BringToFront();
this.TopMost = false;

http://blog.jorgearimany.com/2010/10/win32-setforegroundwindow-equivalent-in.html


I know this is old, but I did not see this response.

In the window (xaml) add:

Deactivated="Window_Deactivated"

In the code behind for Window_Deactivated:

private void Window_Deactivated(object sender, EventArgs e)
    {
        Window window = (Window)sender;
        window.Activate();
    }

This will keep your window on top.


Based on clamum's answer, and Kevin Vuilleumier's comment about the other flag responsible for the behavior, I made this toggle that switches between on-top and not on-top with a button press.

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;
        }
    }

참고URL : https://stackoverflow.com/questions/683330/how-to-make-a-window-always-stay-on-top-in-net

반응형