// ---------------------------------------------------------------------------- // Direct X Demo // (c) 2003 Pavel Tisnovsky // // Tento program otestuje zakladni vlastnosti knihovny DirectDraw. // ---------------------------------------------------------------------------- #include #include #include #include #include #define FULLSCREEN 1 // 1-prejit do plne obrazovky, jinak zustat v rozliseni desktopu #define SET_DISPLAY_MODE 1 // 1-nastavit rezim obrazovky, jinak zustat v rozliseni desktopu #define SET_PALETTE 1 // 1-nastavit paletu, jinak nechat paletu systemovou #define SCREEN_WIDTH 800 // sirka obrazovky v pixelech #define SCREEN_HEIGHT 600 // vyska obrazovky v pixelech #define SCREEN_BPP 8 // pocet bitu na pixel typedef struct { LPDIRECTDRAW directDraw; // objekt DirectDraw LPDIRECTDRAWSURFACE primarySurface; // framebuffer LPDIRECTDRAWSURFACE secondarySurface; // framebuffer DDSURFACEDESC primarySurfaceDesc; // struktura s popisem framebufferu LPDIRECTDRAWPALETTE palette; // paleta PALETTEENTRY paletteEntry[256]; // data palety unsigned char color; // platna barva kresleni } DirectDraw; DirectDraw dd; // instance predchozi struktury HWND hwndMain=NULL; // handle hlavniho okna aplikace // hlavicky pouzitych funkci LRESULT CALLBACK MainWindowProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR commandLine, int ShowMode); void directDrawError(char *errmsg); int directDrawOpen(HWND hwnd, int width, int height, int bpp, int fullScreen, int setMode, int setPalette); int directDrawClose(void); unsigned char * directDrawLockSurface(void); int directDrawUnlockSurface(void); int directDrawClearSurface(void); void directDrawSetColor(unsigned char color); void directDrawPutpixel(int x, int y, unsigned char color); void directDrawHLine(int x1, int x2, int y); void directDrawVLine(int x, int y1, int y2); void Flip() { dd.primarySurface->Flip( NULL, DDFLIP_WAIT ); } // ---------------------------------------------------------------------------- // ukazka vykresleni zakladnich objektu pomoci DirectDraw // ---------------------------------------------------------------------------- void drawExample(float p0 = 5.0f, float p1 = 4.0f) { float x, y, a; for (a=0; a<360.0f; a+=0.05f) { x=300.0f+200.0f*cos(a*3.1415f/180.0f*p0); y=300.0f+200.0f*sin(a*3.1415f/180.0f*p1); directDrawPutpixel((int)x, (int)y, (unsigned char)(127.0f*(cos(7.0f*a*3.1415f/180.0)+1.0f))); } directDrawSetColor(255); directDrawHLine(100, 500, 100); directDrawHLine(100, 500, 500); directDrawVLine(100, 100, 500); directDrawVLine(500, 100, 500); Flip(); } // ---------------------------------------------------------------------------- // ukazka vykresleni zakladnich objektu pomoci DirectDraw // ---------------------------------------------------------------------------- void drawExampleAnime(void) { //float f0=1.0f; for(float f0=1.0f; f0<5.0f; f0+=0.5) drawExample(f0, f0+1.0f); } void xkalab00() { directDrawSetColor(255); srand(time(NULL)); int x1 = (float(rand()) / RAND_MAX) * SCREEN_WIDTH; int y1 = (float(rand()) / RAND_MAX) * SCREEN_HEIGHT; int x2 = (float(rand()) / RAND_MAX) * SCREEN_WIDTH; int y2 = (float(rand()) / RAND_MAX) * SCREEN_HEIGHT; unsigned short vmax = 5; short v1x = (float(rand()) / RAND_MAX) * vmax + 1; short v1y = (float(rand()) / RAND_MAX) * vmax + 1; short v2x = (float(rand()) / RAND_MAX) * vmax + 1; short v2y = (float(rand()) / RAND_MAX) * vmax + 1; while (1) { directDrawClearSurface(); x1 += v1x; if (x1 <= 0) { v1x *= -1; x1 = 0; } else if (x1 >= SCREEN_WIDTH) { v1x *= -1; x1 = SCREEN_WIDTH - 1; } y1 += v1y; if (y1 <= 0) { v1y *= -1; y1 = 0; } else if (y1 >= SCREEN_HEIGHT) { v1y *= -1; y1 = SCREEN_HEIGHT - 1; } x2 += v2x; if (x2 <= 0) { v2x *= -1; x2 = 0; } else if (x2 >= SCREEN_WIDTH) { v2x *= -1; x2 = SCREEN_WIDTH - 1; } y2 += v2y; if (y2 <= 0) { v2y *= -1; y2 = 0; } else if (y2 >= SCREEN_HEIGHT) { v2y *= -1; y2 = SCREEN_HEIGHT - 1; } directDrawHLine(x1, x2, y1); directDrawHLine(x1, x2, y2); directDrawVLine(x1, y1, y2); directDrawVLine(x2, y1, y2); Flip(); } } // ---------------------------------------------------------------------------- // reakce na otevreni hlavniho okna aplikace // ---------------------------------------------------------------------------- void onCreate(HWND hWnd) { } // ---------------------------------------------------------------------------- // reakce na zruseni hlavniho okna aplikace // ---------------------------------------------------------------------------- void onDestroy(HWND hWnd) { directDrawClose(); } // ---------------------------------------------------------------------------- // reakce na stisk klavesy // ---------------------------------------------------------------------------- void onKeyPress(HWND hwnd, unsigned char key) { switch (key) { case 'c': directDrawClearSurface(); Flip(); break; case 'd': drawExample(); break; case 'f': drawExampleAnime(); break; case 'a': xkalab00(); break; } } // ---------------------------------------------------------------------------- // reakce na zadost o prekresleni okna // ---------------------------------------------------------------------------- void onPaint(HWND hWnd) { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } // ---------------------------------------------------------------------------- // hlavni smycka zprav // ---------------------------------------------------------------------------- LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: // zprava generovana pri vytvoreni okna onCreate(hwnd); break; case WM_DESTROY: // zprava generovana pri uzavirani okna onDestroy(hwnd); PostQuitMessage(0); break; case WM_CLOSE: // zprava generovana pred uzavrenim okna DestroyWindow(hwnd); break; case WM_CHAR: // zprava generovana pri stlaceni klavesy if (wParam==27) DestroyWindow(hwnd); else onKeyPress(hwnd,(unsigned char)wParam); break; case WM_PAINT: // zprava generovana pri pozadavku na prekresleni onPaint(hwnd); break; case WM_KILLFOCUS: // zprava generovana, kdyz okno ztrati fokus directDrawClose(); break; case WM_SETFOCUS: // zprava generovana, kdyz okno ziska fokus directDrawOpen(hwnd, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, FULLSCREEN, SET_DISPLAY_MODE, SET_PALETTE); break; default: // dalsi zpravy return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 1; } // ---------------------------------------------------------------------------- // hlavni funkce GDI aplikace // ---------------------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR commandLine, int ShowMode) { MSG stMsg; WNDCLASS wc; wc.style = CS_HREDRAW|CS_VREDRAW; wc.lpfnWndProc = MainWindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "MAINWINDOW"; if ((RegisterClass(&wc)) == 0) { MessageBox(NULL, "Can't create Window Class", "Error", MB_OK | MB_ICONSTOP); return 0; } if ((hwndMain=CreateWindowEx(WS_EX_TOPMOST, "MAINWINDOW", NULL, WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL)) == NULL) { MessageBox(NULL, "Can't create main window", "Error", MB_OK | MB_ICONSTOP); return 0; } ShowWindow(hwndMain, SW_SHOW); UpdateWindow(hwndMain); directDrawClearSurface(); while (GetMessage(&stMsg, NULL, 0, 0)) { TranslateMessage(&stMsg); DispatchMessage(&stMsg); } return int(stMsg.wParam); } // ---------------------------------------------------------------------------- // Funkce volana pri vyskytu chyby // ---------------------------------------------------------------------------- void directDrawError(char *errmsg) { directDrawClose(); MessageBox(NULL, "DirectDraw error", errmsg, MB_OK | MB_ICONSTOP); ExitProcess(0); } // ---------------------------------------------------------------------------- // Otevreni DirectDraw // ---------------------------------------------------------------------------- int directDrawOpen(HWND hwnd, int width, int height, int bpp, int fullScreen, int setMode, int setPalette) { DWORD dwFlags; int i; // vytvoreni objektu DirectDraw if ((DirectDrawCreate(NULL, &(dd.directDraw), NULL))!=DD_OK) { directDrawError("Can't create direct draw object"); return 0; } if (fullScreen) // ma se vykreslovat do plneho okna dwFlags=DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_NOWINDOWCHANGES; else dwFlags=DDSCL_NORMAL | DDSCL_ALLOWREBOOT; // nastaveni rezimu kooperaci mezi HW a procesem if ((IDirectDraw_SetCooperativeLevel(dd.directDraw, hwnd, dwFlags)) != DD_OK) { directDrawError("Can't set co-operative level"); return 0; } if (setMode) { // ma se nastavit video rezim if ((IDirectDraw_SetDisplayMode(dd.directDraw, width, height, bpp)) != DD_OK) { directDrawError("Can't set display mode"); return 0; } } // nastaveni framebufferu memset(&(dd.primarySurfaceDesc), 0, sizeof((dd.primarySurfaceDesc))); dd.primarySurfaceDesc.dwSize=sizeof(dd.primarySurfaceDesc); dd.primarySurfaceDesc.dwFlags=DDSD_CAPS| DDSD_BACKBUFFERCOUNT; dd.primarySurfaceDesc.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; dd.primarySurfaceDesc.dwBackBufferCount = 1; if ((IDirectDraw_CreateSurface(dd.directDraw, &(dd.primarySurfaceDesc), &(dd.primarySurface), NULL)) != DD_OK) { directDrawError("Can't create primary surface"); return 0; } DDSCAPS ddscaps; ddscaps.dwCaps = DDSCAPS_BACKBUFFER; if( dd.primarySurface->GetAttachedSurface(&ddscaps, &dd.secondarySurface) != DD_OK ) { directDrawError("Can't get secondary surface"); return 0; } if (setPalette) { // nastaveni palety for (i=0; i<256; i++) { // vytvorit barevnou skalu grayscale dd.paletteEntry[i].peRed =(unsigned char)i; dd.paletteEntry[i].peGreen=(unsigned char)i; dd.paletteEntry[i].peBlue =(unsigned char)i; dd.paletteEntry[i].peFlags=(unsigned char)i; } IDirectDraw_CreatePalette(dd.directDraw, DDPCAPS_8BIT, dd.paletteEntry, &(dd.palette), NULL); IDirectDrawSurface_SetPalette(dd.primarySurface, dd.palette); } return 1; } // ---------------------------------------------------------------------------- // Uzavreni DirectDraw // ---------------------------------------------------------------------------- int directDrawClose(void) { if (dd.primarySurface) { // pokud existuje framebuffer IDirectDraw_Release(dd.primarySurface); // zrusit ho dd.primarySurface=NULL; } if (dd.directDraw) { // pokud existuje objekt DirectDraw IDirectDraw_RestoreDisplayMode(dd.directDraw); IDirectDraw_Release(dd.directDraw); // zrusit ho dd.directDraw=NULL; } return 1; // vse probehlo v poradku } // ---------------------------------------------------------------------------- // Ziskani framebufferu do vyhradniho ovladani a vraceni jeho adresy // ---------------------------------------------------------------------------- unsigned char * directDrawLockSurface(void) { dd.primarySurfaceDesc.dwSize=sizeof(dd.primarySurfaceDesc); if (FAILED(IDirectDrawSurface_Lock(dd.secondarySurface, NULL, &(dd.primarySurfaceDesc), DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT, NULL))) { directDrawClose(); directDrawError("Failure Locking Buffer"); return NULL; } return (unsigned char *) dd.primarySurfaceDesc.lpSurface; } // ---------------------------------------------------------------------------- // Vraceni framebufferu zpet systemu (proces se vzdava ovladani) // ---------------------------------------------------------------------------- int directDrawUnlockSurface(void) { if (FAILED(IDirectDrawSurface_Unlock(dd.secondarySurface, NULL))) { directDrawClose(); directDrawError("Failure Unlocking Buffer"); return 0; } return 1; } // ---------------------------------------------------------------------------- // Vymazani cele obrazovky // ---------------------------------------------------------------------------- int directDrawClearSurface(void) { unsigned char *p=directDrawLockSurface(); // ziskat adresu framebufferu if (!p) return 0; memset(p, 0, dd.primarySurfaceDesc.lPitch*dd.primarySurfaceDesc.dwHeight); if (!directDrawUnlockSurface()) return 0; // vratit framebuffer systemu return 1; } // ---------------------------------------------------------------------------- // Nastaveni barvy pro vykreslovani dalsich primitiv // ---------------------------------------------------------------------------- void directDrawSetColor(unsigned char color) { dd.color=color; } // ---------------------------------------------------------------------------- // Tato funkce nakresli na pozici [x, y] pixel // ---------------------------------------------------------------------------- void directDrawPutpixel(int x, int y, unsigned char color) { unsigned char *p=directDrawLockSurface(); // ziskat ukazatel na framebuffer *(p+x+y*dd.primarySurfaceDesc.lPitch)=color; // ulozit barvu do framebufferu directDrawUnlockSurface(); // vratit framebuffer systemu } // ---------------------------------------------------------------------------- // Tato funkce nakresli vertikalni usecku z bodu [x1, y] do bodu [x2, y] // ---------------------------------------------------------------------------- void directDrawHLine(int x1, int x2, int y) { int i; unsigned char *p=directDrawLockSurface(); // ziskat ukazatel na framebuffer if (x1>x2) {x1=x1^x2; x2=x1^x2; x1=x1^x2;} // x1 musi byt mensi nez x2 p+=x1+y*dd.primarySurfaceDesc.lPitch; // prvni pixel usecky for (i=x1; iy2) {y1=y1^y2; y2=y1^y2; y1=y1^y2;} // y1 musi byt mensi nez y2 p+=x+y1*dd.primarySurfaceDesc.lPitch; // prvni pixel usecky for (i=y1; i