Долго не было времени сесть и разобраться. Все таки решил не пользоваться советом 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);