Wprowadzenie do DirectDrawPisanie programów pod DirectDraw należy zacząć od przygotowania wszystkich obiektów, zmiennych itp.(plik nagłówkowy od DirectDraw to ddraw.h, trzeba też dodać ddraw.lib). Na początku deklarujemy obiekt główny DirectDraw wygląda to następująco: LPDIRECTDRAW dd; Aby zainicjować obiekt należy wywołać funkcję DirectDrawCreate. DirectDrawCreate(NULL,dd,NULL); Jej pierwszym argumentem jest identyfikator karty graficznej NULL oznacza aktualną kartę, drugi argument to zadeklarowany obiekt DirectDraw, pod który zostanie zapisany wskaźnik do interfejsu DirectDraw. Jeżeli wszystko będzie ok. to funkcja zwróci DD_OK.(do zmiennej typu HRESULT). Przykład: LPDIRECTDRAW dd; HRESULT hr=DirectDrawCreate(NULL,dd,NULL); if(hr!=DD_OK.) { //Błąd } Następnym krokiem jest ustalenie trybu współpracy. Wykonuje się to przy pomocy funkcji SetCooperativeLevel na rzecz obiektu głównego DirectDraw. Czyli: dd->SetCooperativeLevel(hwnd,dwf); Pierwszym argumentem jest uchwyt do okna aplikacji(typ HWND). Drugim jest flaga która może przyjmować różne wartości np. DDSCL_ALLOWMODEX - tylko z DDSCL_EXCLUSIVE i DDSCL_FULLSCREEN. DDSCL_ALLOWREBOOT - można używać CTRL+ALT+DEL. DDSCL_EXCLUSIVE - tylko z DDSCL_FULLSCREEN. DDSCL_FULLSCREEN - aplikacja pracuje w trybie pełnoekranowym. DDSCL_NORMAL - typowa aplikacja Windows 95. DDSCL_NOWINDOWCHANGES - aplikacji nie można minimalizować. Przykład: LPDIRECTDRAW dd; if(DirectDrawCreate(NULL,dd,NULL)!=DD_OK.) { //błąd; } if(dd->SetCooperativeLevel(mojeokno, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN)!=DD_OK.) { //błąd } Aby zainicjować tryb graficzny należy wywołać funkcję SetDisplayMode na rzecz obiektu głównego. dd->SetDisplayMode(640,480,16); Pierwszym argumentem jest szerokość ekranu, drugim wysokość, a trzecim ilość kolorów w bitach. Przykład kolejny: LPDIRECTDRAW dd; if(DirectDrawCreate(NULL,dd,NULL)!=DD_OK.) { //błąd; } if(dd->SetCooperativeLevel(mojeokno, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN)!=DD_OK.) { //błąd } if(dd->SetDisplayMode(640,480,16)!=DD_OK.) { //błąd } Teraz trzeba stworzyć (stronę) bufor w na którym będą wykonywane operację graficzne. Najpierw należy zadeklarować obiekt struktury LPDIRECTDRAWSURFAC reprezentującą ten bufor i wygląda to tak: LPDIRECTDRAWSURFACE buf1; Po deklaracji obiektu trzeba zadeklarować obiekt struktury DDSURFACEDESC czyli: DDSURFACEDESC ds; Następnie wypełniamy pola struktury ds. Ważniejsze pola to: ds.dwSize - Rozmiar struktury ds.dwFlags - Flaga wskazuje które pole jest ważne, może przyjmować np. - DDSD_BACKBUFFERCOUNT - DDSD_CAPS - DDSD_HEIGHT|DDSD_WIDTH . ds.dwHeight - wysokość strony ds.dwWidth - szerokość strony ds.dwBackBufferCount - ilość niewidocznych stron ds.ddsCaps - struktura DDSCAPS. W strukturze DDSCAPS ważne jest pole dwCaps określające właściwości bufora. Ważniejsze wartości: DDSCAPS_3DDEVICE - bufor może być użyty do renderingu 3D. DDSCAPS_BACKBUFFER - bufor jest niewidoczny, tylna strona. DDSCAPS_FLIP - bufor jest przełączany z innym na zmiane. DDSCAPS_OFFSCREENPLAIN - bufor niewidoczny. DDSCAPS_PRIMARYSURFACE - bufor reprezentuje ekran DDSCAPS_SYSTEMMEMORY - bufor tworzony w pamięci DDSCAPS_TEXTURE - bufor przeznaczony do przechowywania tekstury. DDSCAPS_VIDEOMEMORY - bufor jest tworzony z użyciem pamięci karty graficznej DDSCAPS_WRITEONLY -tylko do odczytu. Przykład: LPDIRECTDRAW dd; if(DirectDrawCreate(NULL,dd,NULL)!=DD_OK.) { //błąd; } if(dd->SetCooperativeLevel(mojeokno, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN)!=DD_OK.) { //błąd } if(dd->SetDisplayMode(640,480,16)!=DD_OK.) { //błąd } LPDIRECTDRAWSURFACE buf1; DDSURFACEDESC ds; ZeroMemory(&ds, sizeof(ds)); ds.dwSize = sizeof(ds); ds.dwFlags = DDSD_CAPS; ds.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; Strona zostaje utworzona po wywołaniu funkcji CreateSurface na rzecz obiektu głównego. dd->CreateSurface(&ds,&buf1,NULL); Pierwszym argumentem jest obiekt struktury DDSURFACEDESC. Jako drugi podaje się obiekt struktury LPDIRECTDRAWSURFACE czyli obiekt bufora. Trzecim argumentem jest NULL. Przykład: LPDIRECTDRAW dd; if(DirectDrawCreate(NULL,dd,NULL)!=DD_OK.) { //błąd; } if(dd->SetCooperativeLevel(mojeokno, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN)!=DD_OK.) { //błąd } if(dd->SetDisplayMode(640,480,16)!=DD_OK.) { //błąd } LPDIRECTDRAWSURFACE buf1,buf2; DDSURFACEDESC ds; ZeroMemory(&ds, sizeof(ds)); ds.dwSize = sizeof(ds); ds.dwFlags = DDSD_CAPS; ds.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if(dd->CreateSurface(&ds,&buf1,NULL)!=DD_OK) { //błąd } ZeroMemory(&ds, sizeof(ds)); ds.dwSize = sizeof(ds); ds.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH; ds.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ds.dwWidth = 100; ds.dwHeight = 100; if(dd->CreateSurface(&ds,&buf2,NULL)!=DD_OK) { //błąd } Stworzone zostały tutaj 2 strony jedna reprezentująca ekran, a druga niewidoczna o rozmiarze 100x100. W przypadku kiedy tworzy się 2 strony i jedna jest widoczna, a druga nie i maja one być przełączane, to przydatna może być funkcja AddAttachedSurface która tworzy kolejkę buforów. Przykład: buf1->AddAttachedSurface(buf2); Funkcja jest wywoływana na rzecz bufora 1, a argumentem jest bufor 2. Po przygotowaniu już wszystkiego można zacząć np. rysować. Aby uzyskać wskaźnik na wykreślacz należy wywołać funkcję GetDC na rzecz obiektu strony. Czyli: HDC hdc; buf1->GetDC(&hdc); Do rysowania można używać funkcji: Ellipse(HDC hdc, int xl, int yl, int xp, int yp); - rysuje elipse hdc - wskaźnik do wyreślacza xl - współrzędna x lewego górnego rogu yl - współrzędna y lewego górnego rogu xp - współrzędna x prawego górnego rogu yp - współrzędna y prawego górnego rogu Rectangle(HDC hdc, int xl, int yl, int xp, int yp); - rysuje prostokąt hdc - wskaźnik do wyreślacza xl - współrzędna x lewego górnego rogu yl - współrzędna y lewego górnego rogu xp - współrzędna x prawego górnego rogu yp - współrzędna y prawego górnego rogu SetPixel(HDC hdc, int xl, int yl, COLORREF col); -rysuje pixel hdc - wskaźnik do wyreślacza xl - współrzędna x yl - współrzędna y col - kolor pixela np. RGB(0,0,0) LineTo(HDC hdc, int x, int y); - rysuje linie od punktu ustawienia wyreślacza hdc - wskaźnik do wyreślacza x - współrzędna x y - współrzędna y TextOut(HDC hdc, int x, int y,char *buf, int rozm); - tekst hdc - wskaźnik do wyreślacza x - współrzędna x y - współrzędna y buf - tablica w której znajduje się tekst rozm - rozmiar tablicy z tekstem Zmiana koloru pędzla odbywa się przy użyciu funkcji CreateSolidBrush - funkcja zwraca wskaźnik na pędzel. Np. CreateSolidBrush(COLORREF col); col - kolor w RGB Przykład: HBRUSH br=CreateSolidBrush(RGB(10,10,10)); Aby utworzyć własne pióro należy wywołać funkcję CreatePen - zwracany jest wskaźnik do utworzonego. Np. CreatePen(int styl, int szer, COLORREF col); styl - styl linii. Główne to: - PS_SOLID normalna linia - PS_DOT kropkowana linia szer - szerokość lini col - kolor w RGB Przykład: HPEN pen=CreatePen(PS_SOLID,2,RGB(255,255,255)); SelectObject(hdc,pen); Ładowanie do wykreślacza np. koloru pędzla lub koloru pióra odbywa się przy użyciu funkcji SelectObject. SelectObject(HDC hdc,HGDIOBJ hg); hdc - wskaźnik na wyreślacz hg - object ładowany np. pióro, pędzel, bitmapa itp. Przykład: buf1->GetDC(&hdc); HBRUSH bru=CreateSolidBrush(RGB(0,0,0)); SelectObject(hdc,bru); Rectangle(hdc,0,0,10,10); Tworzony jest tutaj wskaźnik do wykreślacza, ładowany do niego pędzel koloru czarnego i rysowany prostokąt. Ważna jest funkcja ReleaseDC, zwalnia ona wykreślacz. ReleaseDC(HDC hdc); Przykład: buf1->Release(hdc); Po wykonaniu operacji graficznych należy wywołać tą funkcję. Temat ten jest taki rozległy że można by napisać parę książek na jego temat. Myślę, że na początek to wystarczy. Powodzenia. Autorem tekstu jest: Tomasz Urbaniak |