• DDraw笔记一个简单的DDraw应用程序


    一个简单的DDraw应用程序 

    方煜宽

    2011.05.13

    上次谈到DDraw是一个组件。组件由接口组成。

    DDraw总共由五个接口组成: 

    IUnknown:所有com接口都必须从这里继承的。(请看相关文章COM笔记-QueryInterface函数

    IDirectDraw:使用DDraw必须创建的主接口对象。

    IDirectDrawSurface:创建、控制和显示的实际显示表面。分主显示表面和从显示表面

    IDirectDrawPalette:创建、加载和控制调色板,以及将它关联到显示表面。

    IDirectDrawClipper:剪切DDraw光栅和位图操作到一些可见显示表面的子集。

     

      

     

    这些接口怎么配合起来成为一个DDraw应用程序的: 

    1.  创建DDraw对象并使用QueryInterface()来得到 一个IDirectDraw7接口,或是直接用DirectDrawCreateEx()创建一个DDraw7接口。用这个接口来设置协作级别和视频模式。

    2.  使用IDirectDrawSurface7接口至少创建 一个主显示表面用以绘图。(如果每个像素为8位或更少我们会用到一个调色板)

    3.  用IDirectDrawPalette接口创建 一个调色板。(注意如果像素高于8位,如16位、24位,32位,没有调色板,现在主流2D游戏多数是16色)

    4.  如果DDraw应用程序要使用窗口,或者要减少位图以免溢出DDraw显示表面的可见边界,我们至少需要合建一个剪裁器并将其尺寸设置为可见窗口的范围。如下图

     

    5.  最后就是在表面上绘图了。

    下面开始介绍一个最简单的DDraw应用程序: 

    创建DDraw对象:

    用来DirectDrawCreateEx来直接创建DDraw对象,声明如下:

      

    HRESULT WINAPI DirectDrawCreateEx(
    GUID FAR
    *lpGUID, // 视频显卡驱动的GUID,NULL表示系统默认的硬件
    LPVOID
    *lplpDD, // 这是返回的接口
    REFIID iid,
    // 请求接口相对应的ID
    IUnknown FAR
    *pUnkOuter // 总是高为NULL
    );

      

    设置协作级别:

    对DDraw来说,我们唯一关心的是视频显示设备,有两种情况:全屏模式和窗口模式。

    用SetCooperativeLevel来设置DDraw的协作级别。声明如下:

    HRESULT SetCooperativeLevel(HWND hWnd, // 窗口句柄,一般使用主窗口句柄
    DWORD dwFlags);
    // 控制标志

    dwFlags控制标志,它直接影响DDraw与Windows之间协作方式。

    SetCooperativeLevel()的控制标记 

    描述

    DDSCL_ALLOWMODEX

    允许使用Mode X (320x200,240,400) 显示模式.公当设置DDSCL_EXCLUSIVE和DDSCL_FULLSCREEN时生效

    DDSCL_ALLOWREBOOT

    允许在排他(全屏)模式下检测到Ctrl+Alt+Del

    DDSCL_EXCLUSIVE

    请求排他级别。此标记需要与DDSCL_FULLSCREEN标记同时作用

    DDSCL_FPUSETUP

    表示调用 程序希望配置FPU以得到最佳的Direct3D性能(禁用度和异常),这样Direct3D不需要每次都明确地FPU。更多信息,请在DirectX SDK中查询“DDraw协作级别和FPU数度”

    DDSCL_FULLSCREEN

    表示使用全屏模式。其他应用程序的GDI将不能写屏,此标记必须与DDSCL_EXCLUSIVE标记同时使用。

    DDSCL_MULTITHREADED

    请求对于多线程安全的DDraw行为。

    DDSCL_NORMAL

    表示应用程序是一个通常的Windows应用程序。这个标记不能与DDSCL_ALLOWMODEX, DDSCL_EXCLUSIVE, 或 DDSCL_FULLSCREEN标记一起使用。

    DDSCL_NOWINDOWCHANGES

    表示不允许DDraw激活时最小化或还原应用程序窗口。

    上面写了一大堆标记,其实大多数情况是下面两种情况。

    全屏模式:DDSCL_FPUSETUP | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT

    窗口模式:DDSCL_NORMAL

    下面例子:

    因为是用于学习,没有把框架搞得太复杂,全写在一个cpp里了。

    关于怎么写一个GUI应用程序,可以查看《一个简单的windows GUI应用程序

    http://www.cnblogs.com/fangyukuan/archive/2010/08/31/1814159.html

    源代码下载

    //-------------------------------------------------------------------------
    // 文件名 : 6_1.cpp
    // 创建者 : 方煜宽
    // 邮箱 : fangyukuan@gmail.com
    // 创建时间 : 2010-12-1 23:37
    // 功能描述 : 一个简单的DDraw应用程序
    // 注意在工程中把ddraw.lib包含进去
    // -------------------------------------------------------------------------
    #define INITGUID

    #include
    <windows.h>
    #include
    <ddraw.h>

    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

    HWND main_window_handle
    = NULL; // 主窗口句柄
    LPDIRECTDRAW7 lpdd
    = NULL;   // DDraw 对象

    int Game_Init(void *parms = NULL, int num_parms = 0)
    {
    // 创建ddraw对象
    if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
    return(0);

    // 窗口模式(设置协作级别)
    lpdd
    ->SetCooperativeLevel(main_window_handle, DDSCL_NORMAL);
    return 1;
    }

    /////////////////////////////////////////////////////////////
    int Game_Shutdown()
    {
    if (lpdd)
    {
    lpdd
    ->Release();
    lpdd
    = NULL;
    }
    return 1;
    }

    int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nShowCmd)
    {
    HWND hwnd;
    MSG msg;
    TCHAR lpszClassName[]
    = TEXT("kuan");

    WNDCLASS wc;
    wc.style
    = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc
    = WndProc;
    wc.cbClsExtra
    = 0;
    wc.cbWndExtra
    = 0;
    wc.hInstance
    = hInstance;
    wc.hIcon
    = ::LoadIcon(NULL,IDI_APPLICATION);
    wc.hCursor
    = ::LoadCursor(NULL,IDC_ARROW);
    wc.hbrBackground
    = (HBRUSH)::GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName
    = NULL;
    wc.lpszClassName
    = lpszClassName;

    RegisterClass(
    &wc);

    // WS_OVERLAPPEDWINDOW 可以改变窗口大小
    // WS_OVERLAPPED 不可以改变窗口大小
    // WS_POPUP 全屏
    hwnd
    = CreateWindow(lpszClassName,
    TEXT(
    "fangyukuan"),
    WS_OVERLAPPEDWINDOW
    | WS_VISIBLE,
    300,80,800,600,
    NULL,
    NULL,
    hInstance,
    NULL);

    main_window_handle
    = hwnd;

    // ::ShowWindow(hwnd,SW_SHOWNORMAL);
    // ::UpdateWindow(hwnd);
    // while(::GetMessage(&msg,NULL,0,0))
    // {
    // ::TranslateMessage(&msg);
    // ::DispatchMessage(&msg);
    // }

    Game_Init();
    while(TRUE)
    {
    if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
    if (msg.message == WM_QUIT)
    break;
    ::TranslateMessage(
    &msg);
    ::DispatchMessage(
    &msg);
    }
    }
    Game_Shutdown();
    return msg.wParam;
    }

    LRESULT CALLBACK WndProc(HWND hwnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam)

    {
    switch(message)
    {
    case WM_LBUTTONDOWN:
    {
    ::MessageBeep(
    0);
    }
    break;
    case WM_DESTROY:
    ::PostQuitMessage(
    0);
    break;
    default:
    return ::DefWindowProc(hwnd,message,wParam,lParam);
    }
    return 0;
    }

     程序运行效果:

     

    转载请保留下面链接

    http://www.cnblogs.com/fangyukuan/archive/2011/05/13/2045951.html

    
  • 相关阅读:
    C#拾遗(一、基本类型)
    JS正则表达式的test()方法检查汉字
    从程序员到项目经理(一)
    程序员基本素质要求
    似乎比较快
    Qt常用类
    QT 获取窗口 大小 信息
    QT 获取屏幕尺寸的法子
    Qt中 QString 和int, char等的“相互”转换
    qt 读取xml文件
  • 原文地址:https://www.cnblogs.com/fangyukuan/p/2045951.html
Copyright © 2020-2023  润新知