0

I want to create Windows 10 desktop widget. I created C# WinForms project, and using WinAPI I track switching between windows, and when desktop is shown, I show my form. Is there an easier way to do this? I think, I can show my form under all other windows, but i don't know, how to do it. Full code of my existing form:

    public partial class Form1 : Form
    {
        WINEVENTPROC foregroundChanged => new WINEVENTPROC(ForegroundChanged);

        public Form1()
        {
            InitializeComponent();

            SafeHandle foregroundHook = PInvoke.SetWinEventHook(
                PInvoke.EVENT_OBJECT_FOCUS,
                PInvoke.EVENT_OBJECT_FOCUS,
                null,
                foregroundChanged,
                0,
                0,
                PInvoke.WINEVENT_OUTOFCONTEXT | PInvoke.WINEVENT_SKIPOWNPROCESS);

            foreach (var scrn in Screen.AllScreens)
            {
                if (scrn.Bounds.Contains(this.Location))
                {
                    this.Location = new Point(scrn.Bounds.Right - this.Width, scrn.Bounds.Top);

                    return;
                }
            }
        }

        unsafe struct PathBuffer
        {
            public fixed char Buffer[(int)PInvoke.MAX_PATH];
        }

        private unsafe uint GetProcessPidByHWND(HWND hWND)
        {
            uint dwProcessId = 0;

            PInvoke.GetWindowThreadProcessId(hWND, &dwProcessId);

            return dwProcessId;
        }

        private unsafe string GetProcessPathByHWND(HWND hWND)
        {
            uint pid = GetProcessPidByHWND(hWND);

            SafeFileHandle process = PInvoke.OpenProcess_SafeHandle(
                Windows.Win32.System.Threading.PROCESS_ACCESS_RIGHTS.PROCESS_VM_READ
                | Windows.Win32.System.Threading.PROCESS_ACCESS_RIGHTS.PROCESS_QUERY_INFORMATION,
                false,
                pid);

            PathBuffer pathBuffer = new PathBuffer();
            PWSTR pathPWSTR = new PWSTR(pathBuffer.Buffer);

            PInvoke.GetModuleFileNameEx(process, null, pathPWSTR, PInvoke.MAX_PATH);

            return pathPWSTR.ToString();
        }

        private unsafe void ForegroundChanged(
            HWINEVENTHOOK hWinEventHook,
            uint eventType,
            HWND hwnd,
            int idObject,
            int idChild,
            uint dwEventThread,
            uint dwmsEventTime)
        {
            uint desktopPid = GetProcessPidByHWND(PInvoke.GetShellWindow());
            uint currPid = GetProcessPidByHWND(PInvoke.GetForegroundWindow());

            if (desktopPid == currPid)
            {
                Show();
            }
            else
            {
                Hide();
            }
        }
    }
  • 2
    You can use [`SetWindowPos(HWND_BOTTOM)`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos) to move your window to the bottom of the Z-order. But this is the wrong approach. Windows 10 removed native support for desktop widgets (aka [Gadgets](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/gadgetplatform/introduction-to-the-gadget-platform)), but there are 3rd party solutions that add widget support back in. You should consider designing your app to work with one of those APIs instead so it acts like a real widget and not just some hack. – Remy Lebeau Aug 28 '23 at 19:55
  • https://stackoverflow.com/questions/10009623/keeping-window-visible-through-show-desktop-wind – Hans Passant Aug 28 '23 at 21:05

0 Answers0