Регистрация Главная Сообщество
Сообщения за день Справка Регистрация
Навигация
Zhyk.org LIVE! Реклама на Zhyk.org Правила Форума Награды и достижения Доска "почета"

Рисуем поверх графики в окне Perfect World

-

Разработка ПО для Perfect World

- Бюро разработчиков Zhyk.Ru: создание ботов, снифферов и прочих программ для Perfect World

Ответ
 
Опции темы
Старый 22.04.2012, 11:53   #1
 Пехотинец
Аватар для dwa83
 
dwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личность
Регистрация: 21.03.2012
Сообщений: 83
Популярность: 1178
Сказал(а) спасибо: 18
Поблагодарили 101 раз(а) в 53 сообщениях
 
По умолчанию Рисуем поверх графики в окне Perfect World

Многие интересуются проблемой вывода информации прямо в окно PW. Есть примеры, где перехватываются события окончания прорисовки сцены Direct3D и перед сменой буфера прорисовки кадра прорисовывается всё нужное. Мне показалось это слишком замороченным, и потому я попытался найти альтернативный способ вывода своей инфы поверх игры. Это привело меня к способу, которым можно вывести информацию даже без применения DirectX. Я например прикрутил сюда отображение с помощью OpenGL(не люблю Direct3D из-за сложности, а тут всё просто и понятно)

Опишу в чём заключается мой способ на примере программы, сделанной в среде Borland C++ Builder 6.
Для вывода информации нам понадобится окно(буду называть его фреймом), которое мы присоединим к окну PW как дочернее и будем выводить в него то что нам нужно. Для работы нам понадобятся хэндл окна Perfect World и хэндл нашего фрейма.
Опишем их в глобальных переменных. Так же определимся с размерами нашего фрейма, хотя это можно сделать и не здесь.

Код:
HWND win_pw;        // Хэндл окна PW
HWND frame;         // Хэндл нашего фрейма
int frLeft=300;     // Левый отступ фрейма от границы окна-родителя
int frTop=300;      // Отступ сверху от границы окна-родителя
int frWidth=200;    // Ширина фрейма
int frHeight=200;   // Высота фрейма
// Так же я здесь объявлю класс, который я использую для прорисовки с помощью OpenGL.
// Вы будете использовать свой способ отображения
Код:
Tglwindow win;
Далее разместим на форме кнопку для нашего примера. При нажатии на неё будет происходить создание фрейма и присоединение к окну PW как дочернего элемента. Также разместим компонент Timer. Он будет отвечать за прорисовку изображения во фрейме. Нужно по умолчанию его отключить. Включаться он будет при нажатии на кнопку после создания фрейма, когда рисовать уже можно.



Приступим к созданию фрейма. В обработчике клика по кнопке создаём наш компонент.

Код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{

  // Для начала находим хэндл окна PW и помещаем его в нашу глобальную переменную
  win_pw=FindWindow(0,"Perfect World");


  // Функцией CreateWindowEx мы динамически создаём наш фрейм(по сути окно) 
  // функция возвращает хэндл созданного окна
  frame = CreateWindowEx
  (
    WS_EX_LAYERED,                                  // "многослойное" окно
    "STATIC",                                       // класс окна
    "Здравствуй, далёкий Perfect World !",          // заголовок окна
    WS_VISIBLE|WS_CHILD|WS_POPUP,                   // стиль окна
    100,                                            // левая граница окна(размеры мы потом поменяем на нужные)
    100,                                            // верхняя граница окна
    60,                                             // ширина
    20,                                             // высота
    win_pw,                                         // хэндл родительского окна(окна Perfect World)
    (HMENU)NULL ,                                   // хэндл меню(не нужен)
    NULL,                                           // хэндл экземпляра приложения(не указываем)
    NULL                                            // pointer to window-creation data
  );

  // Установим чёрный цвет в роли прозрачного(не отображаемого)
  SetLayeredWindowAttributes(frame, RGB(0, 0, 0), 0x0, LWA_COLORKEY);
  
  // присоединим OpenGL к нашему фрейму для отрисовки графики
  win.glcreate(frame);
  
  // Включаем таймер, отвечающий за прорисовку
  Timer1->Enabled=true;
}
Сделаю несколько пояснений. Я использую функцию CreateWindowEx вместо CreateWindow, так как в ней указываются дополнительные стили, а именно нужный нам WS_EX_LAYERED. Создав окно с указанием этого стиля мы сможем далее использовать такое дополнительное свойство как прозрачность определённого цвета. Это мы делаем для того, чтобы наш фрейм отображался с прозрачным фоном.

указав класс "STATIC" мы создаём окно на подобие компанента Panel, вобщем просто прямоугольную рабочую область. Хотя запросто можно использовать например класс "BUTTON", тогда в окне Perfect World будет отображаться обычная кнопка, в которую так же можно что-либо нарисовать или напечатать.




"Здравствуй, далёкий Perfect World !" - заголовок окна, либо свойство Caption элементов.
стиль окна
WS_VISIBLE - видимое окно
WS_CHILD - является дочерним
WS_POPUP - а это самое главное. Указав это свойство, мы говорим, что наше окно распологается поверх всех элементов родительского окна. Поэтому наш фрейм будет выводиться поверх графики игры. Но здесь появляется одно "НО". Хотя наше дочернее окно и является дочерним от окна игры, сворачивается вместе с ним и т.д., но оно не ограничено областью окна игры и его координаты начинают определяться относительно всего экрана. Таким образом оно может выходить за границы родительского окна. Но это проблему мы решим далее.



Далее приступим к рисованию в нашем фрейме. Пишем код в событии таймера.
Нам нужно решить проблему с вылезанием нашего фрейма за границу окна игры. Мы поступим следующим образом, считаем значения размеров и положения окна игры, и будем позиционировать наш фрейм относительно них. В этом нам поможет функция GetWindowRect, которая получит в структуру типа tagRECT положение нужного окна по его хэндлу. Создадим структуру tagRECT в которую и считаем нужные значения

Код:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{

  tagRECT rect;
  GetWindowRect(win_pw,&rect);
Итак координаты у нас есть, установим положение нашего фрейма относительно полученных координат функцией SetWindowPos

Код:
SetWindowPos(frame,
             HWND_BOTTOM,
             rect.left + frLeft,
             rect.top + frTop,
             frWidth,
             frHeight,
             SWP_NOZORDER);
Теперь наш фрейм позиционирован относительно окна игры. Вот вроде бы и всё готово, можно приступать к рисованию. Я использую OpenGL

Код:
  glClearColor(0.0,0.0,0.0,0.0); // задаём цвет очистки буфера кадра чёрным
  win.clear();                   // очищаем буфер
  glLoadIdentity();              // сбросим матрицу
  glTranslatef(0.0,0.0,-6.0);    // "отодвинем" изображение от зрителя на 6 единиц 

  glBegin(GL_TRIANGLES); // начало сцены
    // GL_TRIANGLES - каждые 3 вершины образуют треугольник
    glVertex3f( 0.0f, 1.0f, 0.0f); // верх
    glVertex3f(-1.0f,-1.0f, 0.0f); // слева снизу
    glVertex3f( 1.0f,-1.0f, 0.0f); // справа снизу
  glEnd(); // конец сцены

  win.swapbuffer(); // смена буферов, делаем буфер кадра видимым

}
Я очищаю буфер кадра в чёрный цвет, таким образом при выводе на наш фрейм этот цвет будет прозрачным. Далее я для примера просто рисую белый треугольник на чёрном фоне(который станет прозрачным).



Вот собственно и всё, что я хотел поведать. В работе с WinAPI я разбираюсь плохо, потому может быть куча недочётов в примере. Например, знающие люди могут создать фрейм изначально с чёрным фоном и просто средствами WinAPI печатать в него текст, тоесть вообще обойтись без графических библиотек и использовать только вывод стедствами Windows. Так же можно растянуть наш фрейм по размерам всего окна PW, и мы будем рисовать в него так, как будто рисовали бы в окно игры относительно его координат. Так же в данном примере присутствуют некоторые побочные артефакты, например игра реагирует на поворот камеры правой кнопкой мыши как-то "необычно". Возможно этот способ можно реализовать проще и он нуждается в доработке, но здесь я просто показал суть способа.
________________
╔═╗
ˑ ˑ ╬ ╬
╚═╝

Последний раз редактировалось dwa83; 23.04.2012 в 20:17.
  Ответить с цитированием
Ответ


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

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

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

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[Обменяю] World of Tanks на Perfect World Saiks Perfect World 4 17.10.2011 18:46
[Пакеты] Руссификаторы Perfect World China(Китай) и Perfect World International $2RIK$ Боты, скрипты и прочий софт для Perfect World 24 22.07.2011 10:32

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

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

Пишите нам: [email protected]
Copyright © 2024 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net