LECKÉK:              

Saját ablak
Directdraw1
Directdraw2
Directdraw_3
Sprite_1

Sprite 2
Billentyű_1
Billentyű_2
Egér
Joystick
Midi
MP3
Directsound
Időzítők
Filekezelés
 

Üdvözöllek!

Most egy directx alapú billentyűkezelést próbálunk létrehozni.
Minenek előtt töltsd vissza az előző projectet, vagy törüld az összes billentyűzethez kapcsolódó függvényt, változót minden fájlban.(main cpp  sprite hpp)
Hozz létre egy új fájl-t Dx_input.hpp néven. Az alaposztály dekralációja:

//
/* INPUT OSZTÁLY */
//
#ifndef _INPUT_
#define _INPUT_
#ifndef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x800

#endif
#include <dinput.h> //MSVC dinput8.lib DEVC++ libdinput.a
//
extern bool fut;
extern HINSTANCE hinstance;
//extern bool aktiv;


//

//dekralációk
//
class INPUT
{
public:
INPUT();
~INPUT();
LPDIRECTINPUTDEVICE8 bill;
bool init_key();
bool init_mause();
bool init_joy();
bool get_key(unsigned char,bool frissit=false);
protected:
LPDIRECTINPUT8 lpDI; //input objektum ezen keresztül hozzuk létre a többit
BYTE key_buf[256];
Akkor ami magyarázatra szorul:
Az input.h  headerhez DEVC++-nál a libdinput.a -t kell, az MSVC hez pedig a dinput.lib kell megadni.
A directinput objektum létrehozásához kell egy HINSTANCE típusú valami,amit megkapunk a main() függvény bemenőparaméteréből.A billentyűzetet majd innen kezeljük,ezért át kell adni azt a logikai változót, (bool fut) anit ha false- ra állítunk, (esc) akkor a progink leáll.:

extern bool fut;
extern HINSTANCE hinstance;

A Directinput objektumot csak egyszer kell létrehozni,és ezen keresztül lehet létrehozni a többi objektumot, mint billentyűzet,egér,joystick. Most a billentyűn a sor, de mint látható elő van készítve az egér és a joy is.Szükség van még egy 256 elemű tömbre is, ami eltárolja az egyes bill. kódokat
Nézzük az init_key() függvényt és a konstruktort, destruktort:

//
//MEGVALÓSÍTÁSOK:
//
INPUT::INPUT()
{
bill=NULL;    //LPDIRECTINPUTDEVICE8 bill pointer nullázása

}
//
INPUT::~INPUT()
{
if(bill){bill->Release();bill=NULL;}// felszabadítjuk
lpDI->Release();lpDI=NULL;        //és az objektumot is törüljük
};
/**/
bool INPUT::init_key()
{
BOOL inf; //infó,hogy sikerült- e a függvény
if( !lpDI)//ha még más nem hozta létre az objektumot
{            //akkor létrehozzuk
inf=DirectInput8Create( hinstance, DIRECTINPUT_VERSION, IID_IDirectInput8A, (VOID**)&lpDI, NULL);
if (inf !=DI_OK)return false;//ha nem sikerült
}
if(bill){bill->Release();bill=NULL;}//ha már létezett letörüljük,egy új példánynak kell a hely
inf=lpDI->CreateDevice(GUID_SysKeyboard, &bill, NULL);//kerálunk billentyűt
if(inf !=DI_OK)return false;
inf=bill->SetDataFormat(&c_dfDIKeyboard);//billentyűzet forma az adat
if(inf !=DI_OK)return false;
inf=bill->SetCooperativeLevel(hwnd,DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
//aktiv=true;
bill->Acquire();//aktiváljuk

return true;
}

Mivel kommentezve van, nincs mit többet mondani.A billentyűzet használatának dekralációja:
bool get_key(unsigned char,bool frissit=false);
A bemenő paraméter egy 0-256 -ig terjedő szám a billentyűről ad vissza információt, hogy le van-e nyomva, vagy mégse. A másik bemenő logikai paraméter pedig az, hogy kell e frissíteni a táblát, mert a használt GetDeviceState(...) függvény minden billentyű állapotot frissít. Tehát ha egymásután több billentyűt kérdezünk le akkor fölösleges újból kitöltetni a táblázatot. Ha a dekralációban true értékkel inicializáljuk,akkor minden meghíváskor frissíti a táblát.
Megvalósítása:
bool INPUT::get_key(unsigned char adat,bool frissit)
{
if(frissit)//ha kell, frissíti a táblát
{
if(bill->GetDeviceState(256,&key_buf)==DIERR_INPUTLOST)
{
init_key(); //amennyiben elveszett az objektum ujraépítjük
return false; //majd következőre lekérdezzük
}
}
if(key_buf[ DIK_ESCAPE] & 0x80)fut=false;//ez a sor biztosítja az esc-re a kilépést
return (key_buf[adat] & 0x80) ? true:false;//lenyomva,vagy mégse

}

Hát ez is kommentezve van, nem sok mondani való maradt,csak annyi,hogy NEM ascII kód kell a billentyűzet lekérdezéséhez, hanem a dinput.h -ban vannak dekralálva az egyes billentyűknek a tömbben elfoglalt helyei , mégpedig el vannak nevezve! pl. a bal kurzornyíl : DIK_LEFT.
Sajnos meg kell nyitni a dinput,h-t és a billentyű nevét meg kell nézni. Azért előny is lehet,mert olyan billentyűt is lekérdezhetünk, amit máshogy nehezebb lenne pl.: DIK_VOLUMEDOWN.
Menjünk a Main,cpp- be!
Vegyük fel a Dx_input.hpp-t és hozzuk létre az új osztályunkat:

#include <windows.h>
#include <Rajz.hpp>
#include <Dx_input.hpp>
#include <Sprite.hpp>

//
//
//dekralációk
HINSTANCE hinstance;
RAJZ rajz;
INPUT input;
SPRITE sprite;

Fontos, a sorrend! mivel a sprite osztály használja majd az input osztályt,ezért ELÉ kell tenni, mert hibaüzit kapnánk....
A következő,hogy van egy HINSTANCE hinstance változó aminek értéket is kell adni:
Módosítsad a WinMain(...) függvényt mindjárt az elején:

 int WINAPI WinMain(HINSTANCE hThisInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nFunsterStil)
{

hinstance=hThisInstance;
WNDCLASSEX wincl; // ITT FOGLALOD LE A STRUKTÚRÁT
.......
.......
Marad az üzenetkezelő függvény bővítése:

switch (message) /* vizsgáljuk az üzenet tipusát */
{
case WM_ACTIVATE: //ha az alkalmazás előtérbe került
if(input.bill==NULL)break;
switch(wParam)
{
case WA_ACTIVE:
case WA_CLICKACTIVE:
aktiv=true; //későbbi felhasználásra
input.bill->Acquire();//aktiváljuk a billentyűzetet
break;
case WA_INACTIVE:
aktiv=false;
input.bill->Unacquire();
break;
}
break;

case WM_DESTROY:
.......
.......

Az aktivate üzenetet azért kell most már figyelni,mert ha az ablakunk kisméretbe került,akkor el kell engedni a billentyűzetet.(és az egeret,meg a joy-t),ha pedig megint aktív, akkor engedni kell a működést. A működés... Ugrás a Sprite.hpp-be!
Mindjárt az elején:
#ifndef DIRECTINPUT_VERSION
#define DIRECTINPUT_VERSION 0x800
#endif
#include "dinput.h"
#include <Dx_input.hpp>

//
extern RAJZ rajz ;
extern bool aktiv;
extern INPUT input;// az új osztály felvétele
Azért kellett ide is csatolni a dinput.h -t mert nem tudnáértelmezni a DIK_LEFT ,DIK_RIGHT stb. billentyűneveket.Dekralálni kéne őket.

 protected tagok  közé vedd fel a void babu_mozgat(); függvényt.
A megvalósítása:

void SPRITE::babu_mozgat()
{
int sebesseg=3; //elmozdulás sebessége
if(!input.get_key(DIK_LEFT,true) & input.get_key(DIK_RIGHT))//ha bal nincs lenyomva de a jobb igen
{
if( sp[0].SP_X < 800-18-sebesseg)sp[0].SP_X+=sebesseg;
}
if(input.get_key(DIK_LEFT) & !input.get_key(DIK_RIGHT))//ha a jobb nincs lenyomva,de a bal igen
{
if( sp[0].SP_X > 0+sebesseg)sp[0].SP_X-=sebesseg;
}
if(!input.get_key(DIK_UP) & input.get_key(DIK_DOWN))//ha a fel nincs lenyomva,de a le igen
{
if( sp[0].SP_Y < 600-18-sebesseg)sp[0].SP_Y+=sebesseg;
}
if(input.get_key(DIK_UP) & !input.get_key(DIK_DOWN))//ha a le nincs lenyomva,de a fel igen
{
if( sp[0].SP_Y > 0+sebesseg)sp[0].SP_Y-=sebesseg;
}
}

Ha nem hagytam ki semmit, akkor mennie kell. Fordít- futtat!AZ eddi elkészülteket megcsináltam DEVC++ fordítóval is, és jól működött,.

itt a működő kód:

vissza