1、DirectX几乎可以为你提供对所有设备的硬件级的控制。通过叫做COM的技术,以及一套由Microsoft和硬件厂商共同编写的驱动程序库,就可以达到上述效果。Microsoft提出了一套协议,包括函数、变量、数据结构等等,硬件厂商必须遵守这套协议才能开发与硬件通信的驱动程序。
2、DirectX组件:
DirectDraw、DirectSound、DirectMusic、DirectInput、DirectPlay、DirectSetup、Direct3DRM
Direct3DIM、DirectX Graphics、DirectX Audio、DirectShow
3、在DirectX的下面有两个层分别叫做 HEL(HardWare Emulation Layer)和 HAL(Hardware Abstract Layer)。 原理如下:DirectX是一种具有前瞻性的设计思路,它假定那些高级功能将由硬件实现,但如果硬件不支持其中的某些功能特性,就用到了HAL和HEL双重模式了。
HAL,是直接与硬件对话的一层,HAL是一种设备驱动程序,通常由设备生产商提供,你可以通过常规DirectX调用直接和它进行通信。条件是,只有当硬件能够直接支持你所要求执行的功能的时候HAL才被使用,从而达到加速的效果。
HEL,运用于当硬件不支持你所要求的性能的时候。它通过软件运算完成该项任务,显然,这么处理速度很慢。
4、 DirectDraw:控制视频显示的主要图形渲染和2D位图引擎。所有图形的绘制都必须通过它。
DirectSound:这个DirectX里的音乐组件。它只支持数字化的声音,不支持MIDI。
DirectSound3D:这是DirectX里的3D音乐组件。它允许你把3D效果的声音在空间里任意的定位,仿佛这些物体都是四处漂浮在房间里。
DirectMusic:拥有DirectSound以前不支持的那部分MIDI技术。这个系统实际上可以让你任意创造新鄂音乐。
DirectInput:该系统处理输入设备,它支持力反馈设备。
DirectPlay:这是DirectX里有关网络方面的部分。它可以让你通过因特网,直接连接或者通过其他任何可能出现的媒介来建立抽象的连接。
Direct3DRM:这是Direct3D的保留模式(Ratained Mode)。它是一个高级的,基于对象和帧的3D系统,你可以用它来编写基本的3D程序,它利用了3D加速。
Direct3DIM:这是Direct3D的直接模式(Immediate Mode)。它是DirectX的低级3D支持。
DirectSetup/AutoPlay:它们是类DirectX的组件,允许一个程序通过应用程序在用户的电脑上安装DirectX,并且当光盘被插入电脑以后便直接启动游戏。
DirectX Graphics:DirectDraw和Direct3D的功能合并在DirectX Graphics里,以提高系统性能,并允许在2D世界里使用3D效果。
DirectX Audio: DirectSound和DirectMusic合并在一起。
DirectShow:它用于在Windows平台上播放流媒体的组件。DirectShow能够提供高质量的捕捉和回放多媒体流。它支持很多格式,包括ASF、MPEG、AVI、MP3和WAV文件。
5、 COM对象: 一个COM对象事实上是一个或一套实现了大量接口(interface)的C++类。(基本上,一个接口就是一套函数)。
QueryInterface()是COM的关键,它用于申请一个指向你所希望的接口函数的指针。要实现该请求,你必须要有一个接口标示符号码(Interface ID)。这是一个将唯一的指定给接口的数字,它是128位的。
COM的另一条规则是,如果你已经有了一个接口,你可以一直从这个接口申请任何一个别的接口,条件是该接口出自同样地COM对象。
AddRef(),COM对象使用了一种叫引用计数的技术来跟踪自己的生命周期。
COM的设计者只是使用虚C++类来实现COM,而不要求用户也必须使用C++来访问或者是创建它们。只要你创建的是一个和Microsoft C++编译器在创建虚C++类时所创建的二进制映像一样的映像,那个COM对象就会是COM兼容的。
每一个COM对象以及接口都必须有一个唯一的128位的标示符,让用户用来申请或访问。这些数字通常称之为GUID。更明确点讲,当定义COM接口时,这些数字就叫接口标示符(IID)。
6、
class IGraphic : IUnknow{
public:
virtual int InitGraphics(int mode) = 0;
virtual int SetPixel(int x, int y, int c) = 0;
//more methods...
};
class ISound: IUnknow{
public:
virtual int InitSound(int driver) = 0;
virtual int PlaySound(int note, int vol) = 0;
//more methods
};
class IInput: IUnknow{
public:
virtual int InitInput(int device) = 0;
virtual int ReadStick(int stick) = 0;
//more methods...
};
现在已经创建了所有的接口,让我们接下来创建容器类,这才是COM对象的核心:
class CT3D_Engine: public IGraphic, ISound, IInput{
public:
virtual HRESULT _stdcall QueryInterface(const IID &iid, (void**)ip){...}
virtual ULONG _stdcall AddRef(){...} //_stdcall 使得参数从右向左一次入栈
virtual ULONG _stdcall Release(){...}
//implement each interface now
virtual int InitGraphics(int mode){...}
virtual int SetPixel(int x, int y, int c){...}
virtual int InitSound(int driver){...}
virtual int PlaySound(int note, int vol){...}
virtual int InitInput(int device){...}
virtual int ReadStick(int stick){...}
private:
//...locals
};
typedef struct _GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[ 8 ];
} GUID;
typedef GUID IID;
7、
myInterface.h
#ifndef __INTERFACE__
#define __INTERFACE__
#include <objbase.h>
#include <stdio.h>
#include <iostream>
#include <malloc.h>
const IID IID_IX = {
0xea67aab3, 0xbe5a, 0x433a,
{ 0xba, 0x86, 0xd9, 0xd1, 0x33, 0xca, 0x14, 0x60}};
const IID IID_IY = {
0xce38cfbe, 0x59cb, 0x480a,
{ 0x9d, 0x57, 0x30, 0x2a, 0xe8, 0xec, 0x2c, 0xaf}};
class IX : public IUnknown
{
public:
virtual void _stdcall fx(void) = 0;
};
class IY : public IUnknown
{
public:
virtual void _stdcall fy(void) = 0;
};
class CCOM_OBJECT : public IX, public IY
{
friend IUnknown *myCoCreateInstance(void);
private:
CCOM_OBJECT() : ref_count(0){}
~CCOM_OBJECT(){}
private:
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
__RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef( void);
virtual ULONG STDMETHODCALLTYPE Release( void);
public:
virtual void _stdcall fx(void)
{
std::cout<<"Function fx has been called."<<std::endl;
}
virtual void _stdcall fy(void)
{
std::cout<<"Function fy has been called."<<std::endl;
}
private:
int ref_count;
};
#endif
myInterface.cpp
#include "myInterface.h"
HRESULT STDMETHODCALLTYPE CCOM_OBJECT::QueryInterface(REFIID riid,__RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
if(riid == IID_IUnknown)
{
std::cout<<"Requesting IUnknown interface"<<std::endl;
*ppvObject = (IX *)this;
}
else if(riid == IID_IX)
{
std::cout<<"Requesting IX interface"<<std::endl;
*ppvObject = (IX *)this;
}
else
{
std::cout<<"Requesting IY interface"<<std::endl;
*ppvObject = (IY *)this;
}
((IUnknown *)(*ppvObject))->AddRef();
return S_OK;
}
ULONG STDMETHODCALLTYPE CCOM_OBJECT::AddRef( void)
{
std::cout<<"Adding a reference"<<std::endl;
return (++ref_count);
}
ULONG STDMETHODCALLTYPE CCOM_OBJECT::Release( void)
{
std::cout<<"Deleteing a reference"<<std::endl;
if(--ref_count == 0)
{
delete this;
return 0;
}
else
return ref_count;
}
main.cpp
#include "myInterface.h"
IUnknown *myCoCreateInstance(void)
{
IUnknown *comm_obj = (IX *)(new CCOM_OBJECT);
std::cout<<"Creating Comm object"<<std::endl;
comm_obj->AddRef();
return comm_obj;
}
int main()
{
IUnknown *punknown = myCoCreateInstance();
IX *pix = NULL;
IY *piy = NULL;
punknown->QueryInterface(IID_IX, (void **)&pix);
pix->fx();
pix->Release();
punknown->QueryInterface(IID_IY, (void **)&piy);
piy->fy();
piy->Release();
punknown->Release();
return 0;
}
2、DirectX组件:
3、在DirectX的下面有两个层分别叫做 HEL(HardWare Emulation Layer)和 HAL(Hardware Abstract Layer)。 原理如下:DirectX是一种具有前瞻性的设计思路,它假定那些高级功能将由硬件实现,但如果硬件不支持其中的某些功能特性,就用到了HAL和HEL双重模式了。
HAL,是直接与硬件对话的一层,HAL是一种设备驱动程序,通常由设备生产商提供,你可以通过常规DirectX调用直接和它进行通信。条件是,只有当硬件能够直接支持你所要求执行的功能的时候HAL才被使用,从而达到加速的效果。
HEL,运用于当硬件不支持你所要求的性能的时候。它通过软件运算完成该项任务,显然,这么处理速度很慢。
4、 DirectDraw:控制视频显示的主要图形渲染和2D位图引擎。所有图形的绘制都必须通过它。
5、 COM对象: 一个COM对象事实上是一个或一套实现了大量接口(interface)的C++类。(基本上,一个接口就是一套函数)。
QueryInterface()是COM的关键,它用于申请一个指向你所希望的接口函数的指针。要实现该请求,你必须要有一个接口标示符号码(Interface ID)。这是一个将唯一的指定给接口的数字,它是128位的。
COM的另一条规则是,如果你已经有了一个接口,你可以一直从这个接口申请任何一个别的接口,条件是该接口出自同样地COM对象。
AddRef(),COM对象使用了一种叫引用计数的技术来跟踪自己的生命周期。
COM的设计者只是使用虚C++类来实现COM,而不要求用户也必须使用C++来访问或者是创建它们。只要你创建的是一个和Microsoft C++编译器在创建虚C++类时所创建的二进制映像一样的映像,那个COM对象就会是COM兼容的。
每一个COM对象以及接口都必须有一个唯一的128位的标示符,让用户用来申请或访问。这些数字通常称之为GUID。更明确点讲,当定义COM接口时,这些数字就叫接口标示符(IID)。
6、
class IGraphic : IUnknow{
public:
virtual int InitGraphics(int mode) = 0;
virtual int SetPixel(int x, int y, int c) = 0;
//more methods...
};
class ISound: IUnknow{
public:
virtual int InitSound(int driver) = 0;
virtual int PlaySound(int note, int vol) = 0;
//more methods
};
class IInput: IUnknow{
public:
virtual int InitInput(int device) = 0;
virtual int ReadStick(int stick) = 0;
//more methods...
};
现在已经创建了所有的接口,让我们接下来创建容器类,这才是COM对象的核心:
class CT3D_Engine: public IGraphic, ISound, IInput{
public:
virtual HRESULT _stdcall QueryInterface(const IID &iid, (void**)ip){...}
virtual ULONG _stdcall AddRef(){...} //_stdcall 使得参数从右向左一次入栈
virtual ULONG _stdcall Release(){...}
//implement each interface now
virtual int InitGraphics(int mode){...}
virtual int SetPixel(int x, int y, int c){...}
virtual int InitSound(int driver){...}
virtual int PlaySound(int note, int vol){...}
virtual int InitInput(int device){...}
virtual int ReadStick(int stick){...}
private:
//...locals
};
typedef struct _GUID {
} GUID;
typedef GUID IID;
7、
myInterface.h
#ifndef __INTERFACE__
#define __INTERFACE__
#include <objbase.h>
#include <stdio.h>
#include <iostream>
#include <malloc.h>
const IID IID_IX = {
const IID IID_IY = {
#endif
myInterface.cpp
#include "myInterface.h"
HRESULT STDMETHODCALLTYPE CCOM_OBJECT::QueryInterface(REFIID riid,__RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
}
ULONG STDMETHODCALLTYPE CCOM_OBJECT::AddRef( void)
{
}
ULONG STDMETHODCALLTYPE CCOM_OBJECT::Release( void)
{
}
main.cpp
#include "myInterface.h"
IUnknown *myCoCreateInstance(void)
{
}
int main()
{
}