Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > WPF, UWP, WinRT, XAML
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.07.2015, 09:36   #1
Dj_SheLL
Форумчанин
 
Аватар для Dj_SheLL
 
Регистрация: 14.10.2009
Сообщений: 128
Печаль Не отображается дочернее окно рабочего стола

Добрый день, уважаемые форумчане!
Суть моей задачи в следующем:
  1. Сделать основное приложение дочерним окном рабочего стола
  2. Делать другие приложения (любые) дочками первого приложения

Первый пункт я выполнил. Класс DesktopAPI реализует это точно для Windows XP и Windows 7 если это стандартное окно. Если же окно имеет свойства
Код:
AllowsTransparency="True" WindowStyle="None"
, то окна не видно, видно только контуры. Тоже самое свойство распростроняется на дочерние окна это окна, даже если его отображения для Windows стандартное.

Выглядит это следующим образом (см. приложенное изображение). На скриншоте я дважды запускал в дочернем окне рабочего стола ещё одно другое приложение.

Также прикладываю два проекта.

В коде делаю так:
Код:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;

namespace WpfDesktop
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            DesktopAPI.WindowOnDesktopShow(new WindowInteropHelper(this).Handle);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            Process p = Process.Start(@"D:\Мои документы\Visual Studio 2010\Projects\WpfApplication6\WpfApplication6\bin\Debug\WpfApplication6.exe");
            Thread.Sleep(500);
            SetParent(p.MainWindowHandle, new WindowInteropHelper(this).Handle);
        }
    }
}
DesktopAPI.cs
Код:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace WpfDesktop
{
    class DesktopAPI
    {
        static IntPtr hDesktop = IntPtr.Zero;

        delegate bool EnumCallback(IntPtr hwnd, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool IsWindowVisible(IntPtr hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool EnumWindows(EnumCallback lpEnumFunc, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr GetWindow(IntPtr hWnd, GWConstants iCmd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetClassName(IntPtr hWnd, [Out] StringBuilder buf, int nMaxCount);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        enum GWConstants : int
        {
            GW_HWNDFIRST,
            GW_HWNDLAST,
            GW_HWNDNEXT,
            GW_HWNDPREV,
            GW_OWNER,
            GW_CHILD,
            GW_MAX
        }

        static string GetClassNameFromHWND(IntPtr hWnd)
        {
            StringBuilder sb = new StringBuilder(256);
            int len = GetClassName(hWnd, sb, sb.Capacity);
            if (len > 0)
                return sb.ToString(0, len);

            throw new Win32Exception(Marshal.GetLastWin32Error());
        }

        static bool EnumWins(IntPtr hWnd, IntPtr lParam)
        {
            if (hWnd != IntPtr.Zero)
            {
                IntPtr hDesk = GetWindow(hWnd, GWConstants.GW_CHILD);
                if (hDesk != IntPtr.Zero && GetClassNameFromHWND(hDesk) == "SHELLDLL_DefView")
                {
                    hDesk = GetWindow(hDesk, GWConstants.GW_CHILD);
                    if (hDesk != IntPtr.Zero && GetClassNameFromHWND(hDesk) == "SysListView32")
                    {
                        hDesktop = hDesk;
                        return false;
                    }
                }
            }
            return true;
        }

        public static void WindowOnDesktopShow(IntPtr window)
        {
            if (hDesktop != IntPtr.Zero && !IsWindowVisible(hDesktop))
                SetParent(window, hDesktop);
            else
            {
                EnumWindows(new EnumCallback(EnumWins), (IntPtr)5);
                SetParent(window, hDesktop);
            }
        }
    }
}
Изображения
Тип файла: jpg 1.jpg (90.9 Кб, 130 просмотров)
Вложения
Тип файла: rar WpfDesktop.rar (314.2 Кб, 8 просмотров)
Тип файла: rar WpfApplication6.rar (478.1 Кб, 7 просмотров)
Dj_SheLL вне форума Ответить с цитированием
Старый 17.07.2015, 12:58   #2
ResourceSpace
Форумчанин
 
Аватар для ResourceSpace
 
Регистрация: 30.06.2015
Сообщений: 353
По умолчанию

Цитата:
дочерним окном рабочего стола
Это не так-то тривиально, как может показаться. Как оно сообщения будет получать? Для чего вообще так делать?
ResourceSpace вне форума Ответить с цитированием
Старый 17.07.2015, 13:33   #3
Dj_SheLL
Форумчанин
 
Аватар для Dj_SheLL
 
Регистрация: 14.10.2009
Сообщений: 128
По умолчанию

Я понимаю, что это не стандартная проблема. Так как на msdn я тоже не нашёл ответов или подсказок.
Это окно и как любое другое будет получать свои сообщения. А так будет дочкой рабочего стола, то приобретает и его свойства - не сворачивается, всегда за другими окнами, не отображается в панели задач, не реагирует на DWM и Aero Peek и т.д.
Для чего мне это нужно - первой целью для создания виджетов, чтобы они были адаптированы от WinXp до Win8. Про 10 молчу, даже в глаза не видел. Второй целью - хочу себе написать свой личный рабочий стол. Считайте это моей прихотью.

Опытным путём обнаружено, что такая проблема существует только при включенном Aero!
Dj_SheLL вне форума Ответить с цитированием
Старый 18.07.2015, 20:23   #4
ResourceSpace
Форумчанин
 
Аватар для ResourceSpace
 
Регистрация: 30.06.2015
Сообщений: 353
Восклицание

Окна в общем случае будут принадлежать разным процессам. Как их можно помещать друг в друга? А если родительское вдруг станет уничтожаться? Да и мне кажется есть риск что не будет часть сообщений получать (оно же станет подчинённым)? Или это только для CHILD...
Цитата:
Если же окно имеет свойства
Цитата:
AllowsTransparency="True"
Начиная с Win2000 появился стиль WS_EX_LAYERED. И с версий Win2000 по Win7 включительно дочерним окнам нельзя иметь этот стиль. Есть подозрение что AllowsTransparency как раз добавляет вашему окну WS_EX_LAYERED. А чужим окнам можете попробовать убирать его перед вызовом SetParent(), но результат может быть не всегда ожидаемым. Да и встречал чужие программы которые как бы по таймеру ставят этот стиль постоянно обратно.
Цитата:
приобретает его свойства - не сворачивается
Засунул в рабочий стол "Блокнот". И разворачивается и сворачивается. Только сворачивается под кнопку Пуск, если панель задач внизу - то так сразу не вернуть.
Цитата:
приобретает его свойства - не отображается в панели задач
Засунул в рабочий стол прогу написанную на Делфи-VCL. Если засовывать в десктоп TForm - то в панели задач останется, а если засовывать TApplication (окно-владелец всех форм) - то в панели задач пропадёт, но формы программы останутся как и были.
Цитата:
не реагирует на DWM
А это что значит? DWM - это ж менеджер, он просто всем управляет.
Цитата:
хочу себе написать свой личный рабочий стол
Вроде подобное следует делать путём написания Shell Extension или замены для Shell, точно не припомню.




P.S. Гаджеты (во всяком случае официальные от Windows) не являются дочерними окнами. Ни к десктопу ни к чему-либо ещё. Просто окно верхнего уровня.

P.P.S. Добавил вложение, exe-программа с 4-мя окнами, возможно пригодится для тренироваться.
Вложения
Тип файла: zip Delphi_VCL_SomeTests_v21.zip (282.7 Кб, 8 просмотров)

Последний раз редактировалось ResourceSpace; 19.07.2015 в 03:28.
ResourceSpace вне форума Ответить с цитированием
Старый 20.07.2015, 11:02   #5
Dj_SheLL
Форумчанин
 
Аватар для Dj_SheLL
 
Регистрация: 14.10.2009
Сообщений: 128
По умолчанию

Цитата:
Сообщение от ResourceSpace Посмотреть сообщение
А если родительское вдруг станет уничтожаться? Да и мне кажется есть риск что не будет часть сообщений получать (оно же станет подчинённым)?
С чего оно вдруг станет уничтожаться? Мне в принципе и не важно, что часть каких-то сообщение не дойдёт - главное, что будет верная перерисовка при каких-то изменениях в окнах.
Цитата:
Сообщение от ResourceSpace Посмотреть сообщение
Начиная с Win2000 появился стиль WS_EX_LAYERED. И с версий Win2000 по Win7 включительно дочерним окнам нельзя иметь этот стиль. Есть подозрение что AllowsTransparency как раз добавляет вашему окну WS_EX_LAYERED.
Да, и правда есть, проаназировал с помощью Spy++.
Цитата:
Сообщение от ResourceSpace Посмотреть сообщение
А чужим окнам можете попробовать убирать его перед вызовом SetParent(), но результат может быть не всегда ожидаемым. Да и встречал чужие программы которые как бы по таймеру ставят этот стиль постоянно обратно.
А не подскажите, как убрать? Через SetLayeredWindowAttributes?
Цитата:
Сообщение от ResourceSpace Посмотреть сообщение
Засунул в рабочий стол "Блокнот". И разворачивается и сворачивается. Только сворачивается под кнопку Пуск, если панель задач внизу - то так сразу не вернуть.
Я имел в виду если пользовать Win+D или Win+M. ControlBar (Minimize, Maximaze и т.д.) на форме не будет - окна будут все не стандартной формы.
Цитата:
Сообщение от ResourceSpace Посмотреть сообщение
P.S. Гаджеты (во всяком случае официальные от Windows) не являются дочерними окнами. Ни к десктопу ни к чему-либо ещё. Просто окно верхнего уровня.
P.P.S. Добавил вложение, exe-программа с 4-мя окнами, возможно пригодится для тренироваться.
Спасибо, изучу.
Dj_SheLL вне форума Ответить с цитированием
Старый 20.07.2015, 12:09   #6
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,964
По умолчанию

Сейчас не могу сказать конкретно (лето, ремонт), но, похоже, нужно копать в сторону API.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Старый 20.07.2015, 15:41   #7
ResourceSpace
Форумчанин
 
Аватар для ResourceSpace
 
Регистрация: 30.06.2015
Сообщений: 353
По умолчанию

Убрать можно примерно так:
Код:
SetWindowLong(wnd, GWL_EXSTYLE, Not WS_EX_LAYERED And GetWindowLong(wnd, GWL_EXSTYLE));
А вот если вам требуется отображать само изображение из Layered... Тут я не знаю.
Когда-то пробовал найти способ, но так как было мало времени, да и поиск был минутной прихотью - не нашёл да бросил.
Может BOBAH13 тогда всё же нашёл способ...
ResourceSpace вне форума Ответить с цитированием
Старый 20.07.2015, 15:56   #8
Smitt&Wesson
Старожил
 
Аватар для Smitt&Wesson
 
Регистрация: 31.05.2010
Сообщений: 13,964
По умолчанию

Вспомнил,эту функцию. Там есть параметр.на месте WS_EX_LAYERED. Эта штука, убирает цвета. В даннгом случае - красный. Лгать не будУ, но все цвета через неё убрать можно.
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder
Smitt&Wesson вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Дочернее окно (MFC / C++) feelmyeyes Помощь студентам 0 27.11.2013 21:28
Дочернее диалоговое окно MFC nubak Помощь студентам 0 14.04.2013 16:34
Дочернее и родительское окно. Sonny01 Помощь студентам 2 30.10.2011 18:11
Дочернее окно StayS Общие вопросы Delphi 2 24.09.2008 20:22