VR
Virtual Reality On-line   DirectX
Новости   |     Журнал    |    Хаkер   |     Магазин   |   Проекты
[   Вход    ]
[Kарта сайтa]
[ Download  ]
[  Конкурс  ]
[  Анекдоты ]
[  Ссылки   ]
[  Реклама  ]
[ Почтальон ]
[ О проекте ]






TopList
Геймер DirectX
DirectDraw без VCL
:

До сегодняшнего дня мы писали DirectX приложения на основе созданной Delphi формы. Мы привязывали к ней DirectDraw и рисовали на ней. Сегодня мы откажемся от этого и напишем приложение на основе своего окна, без использования VCL форм.
Logo
Рис 1. Пример формы

Когда ты создаёшь новый проект, Delphi создаёт главную форму. Она нам не нужны, поэтому её надо удалить. Для этого выбери View -> Project Manager. Перед тобой откроется окно, как на рисунке 1. Щёлкни правой кнопкой крысы по Unit1 . В появившемся меню выбери Remove from project .

Теперь у нас есть пустой проект. Щёлкни правой кнопкой крысы по Project1 . В появившемся меню выбери View Source . Перед тобой откроется вот такой текст:

program Project1;

uses
  Forms;

{$R *.RES}

begin
  Application.Initialize;
  Application.Run;
end.

Лёгким стуком по клавиатуре, преврати этот текст в такой:

program Project1;

uses
  windows,
  messages,
  graphics,
  sysutils,
  forms,
  directx;

{$R *.RES}

var
 Instance: HWnd;//Поток
 WindowClass: TWndClass;//Класс окна
 Handle: HWnd;//Указатель на окно
 msg: TMsg;//Переменная для системных сообщений
//Со следующими переменными мы уже работали
//они нам понадобятся для работы с DirectX
 FDrawObject : IDirectDraw;
 FBackCaps: TDDSCaps;
 FPrimarySurface : IDirectDrawSurface;
 FSecondarySurface : IDirectDrawSurface;
 FSurfaceDescription: TDDSurfaceDesc;
begin
//Получаем новый поток
 instance :=GetModuleHandle(nil);
//Создаём класс окна
 with WindowClass do
  begin
   style:=CS_HRedraw or CS_VRedraw;
   //В Lpfnwndproc присваиваем указатель на процедуру
   //которая будет откликаться на системные сообщения.
   //Эту процедуру я напишу чуть позже.
   Lpfnwndproc:=@windowproc;
   Hinstance:=Instance;
   HbrBackground:= color_btnface;
   LpszClassName:='VR_DX';
   Hcursor:=LoadCursor(0,IDC_ARROW);
  end;
//Регистрируем новый класс
 RegisterClass (WindowClass);
//Создаём окно
 Handle:=CreateWindowEx (0,'VR_DX','',WS_POPUP, 5,5, GetSystemMetrics 
     (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN),0,0,instance, nil);
//Обновляем окно
 UpdateWindow(Handle);

//Здесь мы вставим инициализацию DirectX

// Запускаем цикл, в котором будет проходить проверка 
// системных сообщений.
 while true do
  begin
  //Получить системное сообщение.
   translatemessage(msg);
  //Отправляем его окну
   dispatchmessage (msg);
  //Даём поработать другим
   application.processmessages;
  end;
end.

С большинством кода можно разобраться по комментариям. Я остановлюсь только на одной функции:

Функиция CreateWindowEx создаёт новое окно. Первый параметр - стиль окна, который нам не нужен, поэтому 0. Второй - класс окна. Он должен быть таким же, как и у WindowClass.LpszClassName. Третий - заголовок, который нам тоже не нужен, всё равно его не будет видно. Четвёртый - снова стиль, но немного другой. Здесь нам достаточно WS_POPUP. Следующие два параметра - левая и правая позиции окна. Потом идут ширина и высота. Девятый параметр - указатель на владельца окна. Наше окно главное, поэтому 0. Десятый - указатель на меню. Следующий - указатель на поток. Последний параметр нас тоже не очень интересует.

Теперь напишем процедуру, которая будет откликаться на системные сообщения:

function windowproc (Hwn,msg,wpr,lpr: longint): longint; stdcall;
begin
 //Вызываем обработчик события по умолчанию
 result:=defwindowproc(hwn,msg,wpr,lpr);
 //Если окно уничтожается, то вызвать процедуру DoExit;
 //эту процедуру мы напишем чуть позже
 if msg=wm_destroy then
  DoExit;
 //Если нажата клавиша то ...
 if msg=wm_KeyDown then
  // Если это клавиша ESC то выход
  if wpr=VK_ESCAPE then
   DoExit;
end;

Её нужно вписывать после объявлений var и перед первым begin, иначе Delphi её не найдёт.

Теперь напишем функцию DoExit, которая будет уничтожать окно. Её нужно писать между объявлениями var и процедурой windowproc.

procedure DoExit;
begin
 FSecondarySurface:=nil;
 FPrimarySurface:=nil;
 FDrawObject:=nil;
 Halt;
end;

Здесь всё ясно. Она уничтожает объекты DirectDraw, которые мы ещё не создали :). Давай же создадим их. Напиши следующий текст после токо как мы вызывали UpdateWindow, и перед циклом проверки системных сообщений. Это там, где мы писали смый первый код, я там ещё поставил комментарий, где нужно написать следующее:

 DirectDrawCreate (nil,FDrawObject,nil);
 FDrawObject.SetCooperativeLevel (handle, DDSCL_EXCLUSIVE or 
     DDSCL_FULLSCREEN);

 FDrawObject.SetDisplayMode (800,600,16);
 with FSurfaceDescription do
  begin
   dwSize := sizeof(FSurfaceDescription);
   dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
   ddsCaps.dwCaps :=DDSCAPS_PRIMARYSURFACE or DDSCAPS_FLIP or 
      DDSCAPS_COMPLEX;
   DwBackBufferCount := 1;
  end;
 FDrawObject.CreateSurface (FSurfaceDescription,FPrimarySurface,nil);
 FBackCaps.dwCaps := DDSCAPS_BACKBUFFER;
 FPrimarySurface.GetAttachedSurface (FBackCaps,FSecondarySurface);
 FPrimarySurface.Flip(nil, DDFLIP_WAIT);

Здесь тебе должно быть уже всё ясно. Со всеми процедурами мы уже знакомы.

Программа готова!!! Она ничего не делает, кроме инициализации DirectDraw и создания поверхностей. Вроде бы ничего особенного, но всё это происходит без использования VCL. Если ты захочишь написать быстродействующее прилоение DirectDraw, то тебе придёться писать его именно так.

Если ты захочешь добавить в программу рисование, то обработай сообщение WM_PAINT и рисуй сколько угодно. Для этого нужно подправть процедуру windowproc вот так:

function windowproc (Hwn,msg,wpr,lpr: longint): longint; stdcall;
begin
 result:=defwindowproc(hwn,msg,wpr,lpr);
 if msg=wm_destroy then
  DoExit;
 if msg=wm_paint then
  begin
   //Здесь ты можешь рисовать, сколько тебе влезет.
  end;
 if msg=wm_KeyDown then
  begin
   if wpr=VK_ESCAPE then
    DoExit;
  end;
end;

На сегодня всё.

 Исходники примера забирай здесь


Copyright©: Horrific aka Флёнов Михаил
Design by FMk group©