#include <windows.h>
#include <ddraw.h>
#include <stdio.h>
#include <stdarg.h>
#include "resource.h"
int PASCAL
WinMain(HINSTANCE hInstance,
HINSTANCE
hPrevInstance,
>
LPSTR
lpCmdLine,
>
int nCmdShow)
>{
>
MSG
msg;
>
>
InitApp(hInstance, nCmdShow);
>
>
while (GetMessage(&msg, NULL, 0,
0))
>
{
>
TranslateMessage(&msg);
>
DispatchMessage(&msg);
>
}
>
return msg.wParam;
>}
style="COLOR: red; FONT-SIZE: 10pt; >РАЗЪЯСНЕНИЕ:
>InitApp
>(
>hInstance
>,
>nCmdShow
>) –
style="COLOR: blue"> создает класс окна, в котором
инициализируется
>DirectDraw
>, ниже мы
его создадим.
>Цикл
>while
>–
обработка сообщений с клавиатуры (постоянна, на
протяжении всей программы, пока она не
завершится).
>
>Теперь
рассмотрим
>InitApp
>более
подробно:
>
static
HRESULT
InitApp(HINSTANCE
hInstance, int nCmdShow)
{
HWND
hWnd;
WNDCLASS
wc;
DDSURFACEDESC2
ddsd;
DDSCAPS2
ddscaps;
//
Устанавливаем
>параметры
>окна
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_MAIN_ICON)); style="COLOR: blue">
wc.hCursor = LoadCursor(NULL,
IDC_ARROW);
wc.hbrBackground = (HBRUSH
)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NAME;
wc.lpszClassName = NAME;
RegisterClass(&wc);
//
Создаем
>окно
hWnd = CreateWindowEx(WS_EX_TOPMOST,
NAME,
TITLE,
WS_POPUP,
0,
0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL, style="COLOR: blue">
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
///////////////////////////////////////////////////////////////////////////
//
Создаем
>главный
DirectDraw
объект
///////////////////////////////////////////////////////////////////////////
DirectDrawCreateEx(NULL,
(VOID**)&g_pDD, IID_IDirectDraw7, NULL);
//
Отображение
>окна
:
>полноэкранный
g_pDD->SetCooperativeLevel(hWnd,
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
//
Устанавливаем графический режим 640
x
480
x
8
g_pDD->SetDisplayMode(640,
480, 8, 0, 0);
style="COLOR: blue; FONT-SIZE: 10pt; >
// Создаем
первичный буфер, у которого есть вторичный
ZeroMemory(&ddsd,
sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS |
DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps =
DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
g_pDD->CreateSurface(&ddsd,
&g_pDDSPrimary, NULL);
//
Делаем
>вторичный
>буфер
ZeroMemory(&ddscaps,
sizeof(ddscaps));
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
g_pDDSPrimary->GetAttachedSurface(&ddscaps,
&g_pDDSBack);
//
Устанавливаем
>таймер
style="mso-tab-count: 1">
SetTimer(hWnd, TIMER_ID, TIMER_RATE,
NULL);
return DD_OK;
}
style="COLOR: blue; FONT-SIZE: 10pt; >
А также
после #
include
инициализируем
следующие параметры:
| #define NAME "DDExample1" #define TITLE "Direct Draw Example 1" #define TIMER_ID 1 #define TIMER_RATE 500 LPDIRECTDRAW7 g_pDD = NULL; // Главный DirectDraw объект LPDIRECTDRAWSURFACE7 g_pDDSPrimary = NULL; // Первичная >память DirectDraw LPDIRECTDRAWSURFACE7 g_pDDSBack = NULL; // Вторичная >память DirectDraw static char szMsg[] = "Page Flipping Test: Press F12 to exit"; static char szFrontMsg[] = "Front buffer (F12 to quit)"; static char szBackMsg[] = "Back buffer (F12 to quit)"; |
| long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch ( message ) { // Завершение программы case WM_DESTROY: PostQuitMessage(0); return 0L; // Если нажали клавишу, в данном случае Esc >и F 12 завершает программу case WM_KEYDOWN: switch (wParam) { case VK_ESCAPE: case VK_F12: PostMessage(hWnd, WM_CLOSE, 0, 0); return 0L; } break; style="COLOR: blue; FONT-SIZE: 10pt; > // Скрываем курсор с экрана case WM_SETCURSOR: SetCursor(NULL); return TRUE; // Перерисовываем экран по таймеру, таймер автоматически посылает WM _ TIMER case WM_TIMER: // >Перерисовываем вторичный буфер UpdateFrame ( hWnd ); style="mso-tab-count: 1"> // Меняем местами, первичный со вторичным буфером style="mso-tab-count: 1"> g_pDDSPrimary->Flip(NULL, 0); } return DefWindowProc(hWnd, message, wParam, lParam); } |
|
static
void
UpdateFrame(HWND
hWnd)
{
static BYTE
phase = 0;
HDC
hdc;
DDBLTFX
ddbltfx;
RECT
rc;
SIZE
size;
//
Заполняем выделенную память черным цветом и
затем копируем ее во вторичный буфер
ZeroMemory(&ddbltfx,
sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillColor = 0;
g_pDDSBack->Blt(NULL, NULL, NULL,
DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
// Отрываем контекст
устройства (Кто забудет это сделать, тот не
сможет вывести символы)
g_pDDSBack->GetDC(&hdc);
SetBkColor(hdc, RGB(0, 0, 255));
SetTextColor(hdc, RGB(255, 255, 0));
if
(
phase
)
style="COLOR: blue">
{
style="mso-tab-count: 1">
// Первый раз она пропускается, так как
phase
= 0.
Заносим текст во вторичный буфер
GetClientRect(hWnd,
&rc);
GetTextExtentPoint(hdc, szMsg, lstrlen(szMsg), &size);
TextOut(hdc, (rc.right - size.cx) / 2, (rc.bottom - size.cy) / 2,
szMsg, sizeof(szMsg) - 1);
TextOut(hdc, 0, 0, szFrontMsg, lstrlen(szFrontMsg));
phase
= 0;
}
else
{
// При первом обращении выполняется эта
функция, заносит текст во вторичный
//
буфер
TextOut(hdc, 0, 0, szBackMsg, lstrlen(szBackMsg)); phase = 1; } // Закрываем контекст устройства g_pDDSBack->ReleaseDC(hdc); } |
Открываем контекст устройства для вторичной памяти, потому что именно в ней будут происходить изменения. SetBkColor(hdc, RGB(0, 0, 255)); Устанавливаем фон текста, RGB – красный, зеленый, синий. SetTextColor(hdc, RGB(255, 255, 0));
Устанавливаем цвет самого текста.
if (phase) { GetClientRect(hWnd, &rc); GetTextExtentPoint ( hdc , “Тест переключения страниц: нажмите F 12, чтобы выйти”,
lstrlen (“Тест переключения страниц: нажмите F 12, чтобы выйти”),
& size ); TextOut ( hdc , ( rc . right - size . cx ) / 2, ( rc . bottom - size . cy ) / 2, “Тест переключения страниц:
нажмите F12, чтобы выйти”, sizeof (“Тест переключения страниц: нажмите F 12,
чтобы выйти”) - 1); TextOut ( hdc , 0, 0, “Первичный буфер: ( F 12 выход)”. szFrontMsg , lstrlen (“Первичный буфер:
( F 12 выход)”.)); phase = 0;
} style="COLOR: blue">
Выполняется в том случае, если style=">phase> равна 1 (при первом обращении она не выполняется).
style=">GetClientRect(hWnd, &rc);
Заносит в структуру style=">rc параметры окна, левого верхнего угла, и правого нижнего.
style="COLOR: blue"> GetTextExtentPoint ( hdc , “Тест переключения страниц: нажмите F 12, чтобы выйти”,
lstrlen (“Тест переключения страниц: нажмите F 12, чтобы выйти”), & size ); Заносит в структуру size ширину и высоту данной строки. Которая используется для вывода текста по середине экрана. TextOut( hdc, ( rc.right - size.cx ) / 2, ( rc.bottom - size.cy ) / 2, “Тест переключения страниц: нажмите F12, чтобы выйти”, sizeof (“Тест переключения страниц: нажмите F 12,
чтобы
выйти”) - 1);
Выводим текст в координатах х и y, задав его текст и размер текста.
Один вычитаем, чтобы не было иероглифа.
Переключение страниц:
Затем выводим вторую строку на вторичный буфер, выполняется команда
g_pDDSPrimary->Flip( NULL, 0);
и вторичный буфер мы с Вами увидим на экране, а первичный “прячется”.
Через некоторое время Windows посылает команду WM_TIMER и на этот
раз выполняется if, куда заносятся две строки.