Регистрация Главная Сообщество
Сообщения за день Справка Регистрация

Ренеймер трея с#/WinApi

-

Общение разработчиков

- Программирование для Perfect World, общение и обсуждене разработок

Ответ
 
Опции темы
Старый 05.11.2016, 19:02   #1
 Разведчик
Аватар для KLAIDY
 
KLAIDY никому не известный тип
Регистрация: 11.10.2010
Сообщений: 13
Популярность: 10
Сказал(а) спасибо: 3
Поблагодарили 5 раз(а) в 5 сообщениях
 
По умолчанию Ренеймер трея с#/WinApi

Доброго времени суток. У меня возникла проблема при написании ренеймера. Сам я пишу на С# и с WinApi знаком лишь понаслышке.

Так вот. проблема в следующем. Использую вот такую нехитрую функцию:
Код:
[DllImport("user32.dll")]
        public static extern int SetWindowText(IntPtr hWnd, string text);
Все классно, окно переименовывается, однако ToolTip иконки в трее не меняется.
Нашел на инвоке следующую функцию, но хз, как ей пользоваться:
Код:
[DllImport("shell32.dll")]
static extern bool Shell_NotifyIcon(uint dwMessage,
   [In] ref NOTIFYICONDATA pnid);
Может быть найдется добрый человек, который подскажет и спасет меня от многочасового общения с гуглом?
  Ответить с цитированием
Старый 05.11.2016, 20:22   #2
 Разведчик
Аватар для Simyr
 
Simyr никому не известный тип
Регистрация: 23.10.2010
Сообщений: 7
Популярность: 12
Сказал(а) спасибо: 0
Поблагодарили 7 раз(а) в 5 сообщениях
 
По умолчанию Re: Ренеймер трея с#/WinApi

для PWI достаточно изменить текст находящийся в памяти клиента по адресу EF9054
  Ответить с цитированием
Старый 05.11.2016, 20:27   #3
 Разведчик
Аватар для KLAIDY
 
KLAIDY никому не известный тип
Регистрация: 11.10.2010
Сообщений: 13
Популярность: 10
Сказал(а) спасибо: 3
Поблагодарили 5 раз(а) в 5 сообщениях
 
По умолчанию Re: Ренеймер трея с#/WinApi

Цитата:
Сообщение от SimyrПосмотреть сообщение
для PWI достаточно изменить текст находящийся в памяти клиента по адресу EF9054

А не подскажете, на PWI по каким офсетам находится данный адрес?

UPD: Тупанул что-то, адрес же статичный) Ну в любом случае на офе по этому адресу считывается не то, что хотелось бы)

Последний раз редактировалось KLAIDY; 05.11.2016 в 21:15.
  Ответить с цитированием
Старый 05.11.2016, 21:39   #4
 Разведчик
Аватар для Simyr
 
Simyr никому не известный тип
Регистрация: 23.10.2010
Сообщений: 7
Популярность: 12
Сказал(а) спасибо: 0
Поблагодарили 7 раз(а) в 5 сообщениях
 
По умолчанию Re: Ренеймер трея с#/WinApi

вбить в поиске cheate engine название иконки в трее, проверить статичные адреса путем изменения текста, получить нужный адрес!
  Ответить с цитированием
Старый 16.11.2016, 16:45   #5
 Разведчик
Аватар для KLAIDY
 
KLAIDY никому не известный тип
Регистрация: 11.10.2010
Сообщений: 13
Популярность: 10
Сказал(а) спасибо: 3
Поблагодарили 5 раз(а) в 5 сообщениях
 
По умолчанию Re: Ренеймер трея с#/WinApi

Долго не было времени сесть и разобраться. Все таки решил не пользоваться советом Simyr (как говориться, мы не ищем легких путей хД).
Сразу скажу, что нашел решение своего вопроса частично и очень захотел поделится с миром.
В общем разобрался как работает Shell_NotifyIcon:
Для моей задачи (ренеймер ToolTip в трее) нам нужно создать структуру, но использовать придется только cbSize, хэндл окна, ID иконки (методом тыка было определено, что у пв всегда иконке дается 101 id), флаг (чтобы вам не пришлось гуглить лишнее время, чуть ниже объясню, что за флаг), ну и szTip:

Код:
[StructLayout(LayoutKind.Sequential)]
        public struct NotifyIconData
        {
            public System.UInt32 cbSize; // DWORD
            public System.IntPtr hWnd; // HWND
            public System.UInt32 uID; // UINT
            public NotifyFlags uFlags; // UINT
            public System.UInt32 uCallbackMessage; // UINT
            public System.IntPtr hIcon; // HICON
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public System.String szTip; // char[128]
            public System.UInt32 dwState; // DWORD
            public System.UInt32 dwStateMask; // DWORD
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public System.String szInfo; // char[256]
            public System.UInt32 uTimeoutOrVersion; // UINT
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public System.String szInfoTitle; // char[64]
            public System.UInt32 dwInfoFlags; // DWORD
        }
парочка перечислений на случай других задач:

Код:
public enum NotifyIconMessage : int
        {
            Add = 0x0, Modify = 0x1, Delete = 0x2, SetFocus = 0x3,
            SetVersion = 0x4
        }
public enum NotifyFlags
        {
            Message = 0x1, Icon = 0x2, Tip = 0x4, State = 0x8, Info = 0x16,
            Guid = 0x32
        }
а также сама наша WinApi функция:

Код:
[DllImport("shell32.Dll")]
        public static extern System.Int32 Shell_NotifyIcon(NotifyIconMessage     cmd,  [In] ref NotifyIconData data);
и вот в этом месте у меня возник вопрос, который в принципе решить несложно, но хочется написать в этом месте оптимальный код((
Нужно найти дескриптор окна пвхи.
1) В развернутом окне ищу через свойство процесса MainWindowHandle. В данном случае придется ловить нажатие на крестик каждого окна, чтобы при сворачивании игры менять тултип.
2) В свернутом в трей окне дескриптор помогает найти все тот же WinApi

Код:
[DllImport("user32.dll")]
        public static extern int FindWindow(
        string lpClassName, // class name 
        string lpWindowName // window name
        );


Код:
IntPtr z = (IntPtr)WinApi.FindWindow(null, "Perfect World");
Ну а дальше просто вызываем следующий метод с нашим дескриптором и надписью, которую хотим поставить.

Код:
public void RenameNotify(System.IntPtr hWnd, string newToolTip)
        {
                NotifyIconData data = new NotifyIconData();
                data.cbSize = (System.UInt32)
                              System.Runtime.InteropServices.Marshal.SizeOf(
                                                                    typeof(NotifyIconData));
                data.uFlags = NotifyFlags.Tip;
                data.hWnd = hWnd;
                data.szTip= newToolTip;
                data.uID = 101;
                Shell_NotifyIcon(NotifyIconMessage.Modify, ref data);
        }
        /*
            При  изменении  иконки  необходимо заполнить поля cbSize, hWnd,
            uID,  uFlags  и  поля, отвечающие за параметры иконки, которые вы
             хотите  менять.  При  этом  uFlags  должен  содержать  комбинацию
            флагов, описывающую поля, которые необходимо менять.
         */
Ну а теперь у меня возник вопрос, как лучше сделать? Если пользоваться первым вариантом поиска дескриптора, то опять придется идти гуглить "ловление сворачиваний игры"
Если пользоваться вторым способом, то при разворачивании окна из трея и повторном его сворачивании тултип опять меняется на стандартный. (смотри пункт 1?)
Помогите идеями, пожалуйста

Добавлено через 5 часов 10 минут
В общем я решил, что еще мал для всех этих глобальных хуков и тупо поставил обновление всех треев пв по таймеру
Тяжело было понять, как узнать дескрипторы всех окон, а не только одного. Выложу, потому как найти похожий пример было непросто:
Код:
public void Rename()
            {
                NotifyIcon nf = new NotifyIcon(); //метод переименовывания у меня в отдельном нестатичном классе, не обращайте внимания
                IntPtr hwnd = IntPtr.Zero;
                while (true)
                {
                    hwnd = WinApi.FindWindowEx(IntPtr.Zero, hwnd, "ElementClient Window", null);
                    if (hwnd == IntPtr.Zero) break;
                    int process_id;
                    WinApi.GetWindowThreadProcessId(hwnd, out process_id);
                    nf.RenameNotify(hwnd, hwnd.ToString()); //здесь уже вызываем метод переименовывания, на тултипе пишем дескриптор нашего окна
                }
            }
Ну и в приложение используемые WinApi функции:
Код:
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

Последний раз редактировалось KLAIDY; 16.11.2016 в 21:59. Причина: Добавлено сообщение
  Ответить с цитированием
Ответ


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
С++ и WinAPI alegr Вопросы и ответы, обсуждения 0 19.04.2012 14:58
[Статья] Пишем Ренеймер/Renamer окон [Delphi 7] Хакерок:) Школа Читера 7 09.01.2011 19:33
[Статья] Ренеймер. Используем хук. Amba Школа Читера 4 05.12.2010 01:15
Ренеймер(пв\делфи) jason830 Вопросы и ответы, обсуждения 6 30.09.2010 18:25

Заявление об ответственности / Список мошенников

Часовой пояс GMT +4, время: 09:34.

Пишите нам: forum@zhyk.ru
Copyright © 2025 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net