 在 Windowed Mode(窗口模式) 下使用计时器卷动背景图象。 编译成功后拖曳窗口改变大小,确认图象可以随着画面伸缩。 另外,尝试进一步简化源程序。 卷轴有各种各样的卷法,这回我们用下面的方式卷: 1. 用两张相同的图片左右并排拼成一张。 (下面是我用的图片, 640*240 。用两张 320*240 的图片拼的,命名为 "约塞米蒂山谷.bmp" ,放在 G:\DirectX 8\ 下。)  2. 因为画面的初始大小是 640*480 ,所以把上面的图片扩展到 1280*480 ,储存在 BmpSurface : if (FAILED(hr= g_pDisplay->CreateSurfaceFromBitmap(&g_pBmpSurface, "E:\\DirectX 8\\约塞米蒂山谷.bmp",1280,480))) return hr; 3. 启动计时器控制卷轴速度。 指定计时间隔 20 毫秒: #define ID_TIMER 32767 : SetTimer(hWnd,ID_TIMER,20,NULL); 4. 在计时器(WM_TIMER)中计数 g_cnt : int g_cnt = 0; : case WM_TIMER: g_cnt++; break; 5. 把作为背景描绘的 BmpSurface 的矩形区域设定为 RECT 结构体。 画面初始大小是 640*480 : RECT rt; top= 0; rt.bottom= 480; rt.left= g_cnt%640; rt.right= rt.left+640; 6. 从图片的左端(横坐标 = 0)向中间(横坐标 = 639)一边挪动一边描绘: g_pDisplay->Blt(0,0,g_pBmpSurface,&rt); if (FAILED(hr= g_pDisplay->Present())) return hr; 7. 横坐标达到 640 就返回到左端(横坐标 = 0)。(注意那个 g_cnt%640)。 如果你的图片不是用两张相同的图片左右拼起来的,卷轴的时候看起来就很不舒服:卷到末尾、忽然跳到开头;再卷到末尾、再忽然跳到开头……感觉并不是连续卷轴。你可以把一张图片裁成 640*240 试试。 8. 退出程序时关闭计时器: case WM_DESTROY: KillTimer(hWnd, ID_TIMER); 下面把创建窗口的代码给它尽量简化。 640*480 是窗口的初始大小,我们用 ddutil.cpp 里面的 CreateWindowedDisplay() 函数重新设定窗口大小: WNDCLASS wc = { CS_CLASSDC,WndProc,0L,0L,hInst, NULL,NULL,NULL,NULL,NAME }; if (RegisterClass(&wc)==0) return FALSE; HWND hWnd = CreateWindow(NAME,NAME,WS_OVERLAPPEDWINDOW,0,0,640,480, GetDesktopWindow(),NULL,wc.hInstance,NULL); if (hWnd==NULL) return FALSE; 虽说有 WNDCLASS 和 WNDCLASSEX 两种类型,如果不使用扩展机能,实际上用哪个都一样。 这里开出 WNDCLASSEX 的代码: WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndProc,0L,0L,hInst, NULL,NULL,NULL,NULL,NAME,NULL }; if (RegisterClassEx(&wc)==0) return FALSE; 实际决定窗口大小的 CreateWindowedDisplay() : if (FAILED(hr = g_pDisplay->CreateWindowedDisplay(hWnd,640,480))) { ERMSG("Failed initializing DirectDraw."); return hr; } 下面说明工程的创建方法。 1. 新建一个 Win32 Application 空白工程,命名为 "Scrool"。 2. 向工程中新建一个 C++ Source File ,命名为 "scrool" ,向其中键入篇末附带的源程序。 3. 把下面4个文件复制到工程文件夹(我是 G:\DirectX 8\Scrool\): E:\Mssdk\samples\Multimedia\Common\include\ddutil.h E:\Mssdk\samples\Multimedia\Common\include\dxutil.h E:\Mssdk\samples\Multimedia\Common\src\ddutil.cpp E:\Mssdk\samples\Multimedia\Common\src\dxutil.cpp 然后选择菜单 [Project|工程]-[Add To Project|添加到工程]-[Files...|文件...] ,向工程中添加这4个文件。 4. 准备合适的图象文件(我是在 G:\DirectX 8\ 下放了张 "约塞米蒂山谷.bmp" ,参见本章开头)。 5. 选择菜单 [Project|工程]-[Settings...|设定...] 打开[Project Settings|工程设定] 面板,点击 [Link|链接] 标签,向 [Object/library modules|对象、库模块] 栏内添加下面4个库文件: dxguid.lib ddraw.lib dxerr8.lib winmm.lib 6. 编译并执行! 源程序: /*****************************************/ /*★ 背景卷轴 2001-01-14 前田 稔 ★*/ /*****************************************/ #define NAME "BMP Scrool" #define STRICT #include #include #include #include "ddutil.h" #define ID_TIMER 32767 // Defines, constants, and global variables #define SAFE_DELETE(p) { if (p) { delete (p); (p)=NULL; } } #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } } #define ERMSG(x) MessageBox(hWnd, x, "DirectDraw Samplee", MB_OK); CDisplay* g_pDisplay = NULL; CSurface* g_pBmpSurface = NULL; BOOL g_bActive = FALSE; int g_cnt = 0; // Function-prototypes LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); HRESULT InitDraw(HWND hWnd); VOID FreeDraw(); HRESULT DisplayFrame(); //★ Windows Main int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) { MSG msg; /* WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndProc,0L,0L,hInst, NULL,NULL,NULL,NULL,NAME,NULL }; if (RegisterClassEx(&wc)==0) return FALSE; */ WNDCLASS wc = { CS_CLASSDC,WndProc,0L,0L,hInst, NULL,NULL,NULL,NULL,NAME }; if (RegisterClass(&wc)==0) return FALSE; HWND hWnd = CreateWindow(NAME,NAME,WS_OVERLAPPEDWINDOW,0,0,640,480, GetDesktopWindow(),NULL,wc.hInstance,NULL); if (hWnd==NULL) return FALSE; if (FAILED(InitDraw(hWnd))) { if (g_pDisplay) g_pDisplay->GetDirectDraw()->SetCooperativeLevel(NULL, DDSCL_NORMAL); ERMSG("DirectDraw init failed. The sample will now exit."); return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); SetTimer(hWnd,ID_TIMER,20,NULL); while(TRUE) { if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (0 == GetMessage(&msg, NULL, 0, 0)) return (int)msg.wParam; TranslateMessage(&msg); DispatchMessage(&msg); } else { if (g_bActive) { if (FAILED(DisplayFrame())) { SAFE_DELETE(g_pDisplay); ERMSG("Displaying the next frame failed"); return FALSE; } } else WaitMessage(); } } } //★ WndProc() LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_KEYDOWN: PostMessage(hWnd,WM_CLOSE,0,0); return 0L; case WM_TIMER: g_cnt++; break; case WM_PAINT: if (g_pDisplay) { // Display the new position of the sprite if (DisplayFrame() == DDERR_SURFACELOST) { PostMessage(hWnd,WM_CLOSE,0,0); } } break; case WM_MOVE: if (g_pDisplay) g_pDisplay->UpdateBounds(); return 0L; case WM_SIZE: // Check to see if we are losing our window... if (SIZE_MAXHIDE==wParam||SIZE_MINIMIZED==wParam) g_bActive= FALSE; else g_bActive= TRUE; if (g_pDisplay) g_pDisplay->UpdateBounds(); break; case WM_DESTROY: KillTimer(hWnd, ID_TIMER); FreeDraw(); PostQuitMessage(0); return 0L; } return DefWindowProc(hWnd, msg, wParam, lParam); } //★ InitDraw() HRESULT InitDraw(HWND hWnd) { HRESULT hr; g_pDisplay = new CDisplay(); if (FAILED(hr = g_pDisplay->CreateWindowedDisplay(hWnd,640,480))) { ERMSG("Failed initializing DirectDraw."); return hr; } if (FAILED(hr= g_pDisplay->CreateSurfaceFromBitmap(&g_pBmpSurface, "G:\\DirectX 8\\约塞米蒂山谷.bmp",1280,480))) return
 【责编:admin】
|