Guidance
指路人
g.yi.org
software / rapidq / Examples / Game / directx & direct3d / DirectX Dev / RapidQ_Guide_to_COM.txt

Register 
注册
Search 搜索
首页 
Home Home
Software
Upload

  
OK here is the Quick but Lame Tutorial on DirectX COM interface and RapidQ

First make sure you know the abbreviations:
API - application programming interface. How you talk with the operating system to get it to do what you program asks.

DLL - Dynamic Link Library an EXTERNAL file that contains machine code. Your program can use DLL to run Windows API. DLLs load in the same process space (memory area) as your program. You cannot compile a DLL into your program.

COM - Component Object Model. You never get a straight answer from M$. Basically, this is a standard to improve DLL. Once a COM is made it is standard and new versions will work with older programs. They are suited for C++ coding. It kind of turns DLLs into object oriented programming.

GUID - Globally Unique identifier. A 16-bye code that identifies a specific COM object. That is DirectDraw (one little piece of DirectX) has a GUID that is for a DirectDraw version. That way all new versions are known from old ones and other pieces of DirectX. You might remember the QOLEOBJECT example in which
Microsoft Word has a GUID "{000209FE-0000-0000-C000-000000000046}" that thing has 16 bytes of hexadecimal codes.

POINTER - a variable that holds the memory address (location in computer memory) of a variable, User defined TYPE, a SUB, Func, etc. etc. A pointer tells you WHERE in memory your variable is. The contents of the memory address tells you WHAT the variable value is.
RapidQ does not give you all pointers (see below)
DIM a AS INTEGER
DIM lp AS LONG
A = 5
Lp = VARPTR(a)    'lp is now the pointer, it does not = 5!!! But a memory address.



The BASICs of DirectX
___________________
DirectX uses the COM interface. It is not the same as "OLE automation", which also uses a COM interface but with a different format.

Instead of calling one or many individual SUB/Func like this:
Declare Function GetDesktopWindow Lib "user32" Alias "GetDesktopWindow" () As Long
Declare Function GetForegroundWindow Lib "user32" Alias "GetForegroundWindow" () As Long
Declare Function GetDC Lib "user32" Alias "GetDC" (hwnd As Long) As Long
..... on and on

You are going to have one a (or few) simple calls
Here is the only call you need to start DirectDraw:

Declare Function DirectDrawCreate Lib "ddraw.dll" ALIAS "DirectDrawCreate" (ByVal lpGUID As Long, ByVal lplpDD As Long, ByVal pUnkOuter As Long) As Long

Wow, that was easy! Wrong....

What happens is this Function returns a POINTER TO A STRUCTURE, that can be used to IMPLEMENT the INTERFACE. This is explained later. Here is how you run it:

'test.bas.........................................
$DEFINE LPDIRECTDRAW       LONG  ' variables of "LPxxxx" are pointers
$DEFINE LPDIRECTDRAWSURFACE    LONG  'use LONG for 32-bit windows
$DEFINE IDirectDraw          LPDIRECTDRAW
$DEFINE HRESULT             LONG 'handle for a return value
$DEFINE DD_OK          0          'this checks if it ran OK
'The API to create our DirectDraw "OBJECT"
Declare Function DirectDrawCreate Lib "ddraw.dll" ALIAS "DirectDrawCreate"_
(ByVal lpGUID As Long, ByVal lplpDD As Long, ByVal pUnkOuter As Long) As Long

DIM result       AS HRESULT
DIM lpDD       AS LPDIRECTDRAW    'our pointer
lpDD = 0       'null it out
result = DirectDrawCreate(0, @lpDD,0)  'get the pointer to the interface
'first parameter is 0, which is the default active display
'second parm passes the Pointer of lpDD using the '@' symbol to the FUNCTION
'last parameter must be 0 for 'future expansion' by windows

IF result <> DD_OK THEN
 ShowMessage "Create direct draw Failed"
ELSE
  ShowMessage STR$(lpDD)
END IF
'end of program..............................

This program actually runs and returns a large number in lpDD. This is the starting address of the INTERFACE. IF you run it, you cannot close down the directDraw interface because you are supposed to RELEASE it, so windows can use the memory
Here is the c code:
lpDD->Release();
You can't do it in RapidQ, yet. So if you run the program you just used up some memory...


With the line
result = DirectDrawCreate(0, @lpDD,0)
We now a POINTER TO A STRUCTURE, the pointer is lpDD !! But how do we start calling the DirectDraw functions? You need to declare the structure and then use that pointer to the stucture. You know what a structure is (use TYPE or STRUCT)
   TYPE MyType
        A AS LONG
        B AS LONG
        C AS LONG
        D AS LONG
(etc....)
    END TYPE

In COM you would get the pointer of the structure, then the next variable (MyType.a) would hold the address of the next METHOD (like a SUB or FUNCTION), then the next variable holds the next METHOD address and so on. The important part is that this type is really a table of pointers to subs and functions. The code for a SUB or FUNCTION sits in some memory address space in the computer. The program knows where that code is by a pointer. Pointers are only numbers, and for Windows 32-bit, the pointer is of
a LONG type. The pointer holds the memory address of the starting location of the code. So if you know the value of the pointer, you can "jump" that memory location and run the code in that "process space." Before you can run that code, the program must know how many, and what type of parameters there are to run the code.

For the example above, once you DIM some variable as MyType then you can start calling methods like this
Result = MyType.a(x as integer, y as integer)
You should see how this would work for lots of things in RapidQ like QFORM, QBUTTON, etc.

There is a command called BIND in RapidQ that should do this for you but IT DOES NOT WORK THIS way. Instead it keeps its own internal structure that you can't change. So there is a way to get it to work under rapidq but we need a DLL that can CALL the address and put the right number of parameters in the STACK.

Then what does the DirectDraw structure look like and how does the compiler know how to keep all those parameters straight?

All DIRECTX and Direct3D INTERFACES start with three methods. Implementing them in RapidQ would be something like this:

'Example above get the interface base address
result = DirectDrawCreate(0, @lpDD,0)  'get the pointer to the interface

TYPE IUnknown EXTENDS QOBJECT
PUBLIC:
   DIM lpDD      AS LONG    'interface base pointer address
'the address is passed to lpDD
   DIM InterfaceOffset    AS LONG    'call base address + offset
FUNCTION QueryInterface(BYVAL lpIUnknown AS LONG, _
                    riid AS STRING * 16, ppvObj AS LONG) AS LONG
      InterfaceOffset = 0
   CALLFUNC(lpDD+ InterfaceOffset, lpIUnknown, riid, ppvObj)

FUNCTION AddRef(BYVAL lpIUnknown AS LONG) AS LONG
      InterfaceOffset = 4
   CALLFUNC(lpDD+ InterfaceOffset, lpIUnknown)


FUNCTION Release(BYVAL lpIUnknown AS LONG) AS LONG
      InterfaceOffset = 8
   CALLFUNC(lpDD+ InterfaceOffset, lpIUnknown)
END TYPE

So on and so on. The file DDRAW_001.INC shows the start of directX development in RQ. ...
掌柜推荐
 
 
 
 
 
 
 
 
 
 
 
 
© Thu 2024-4-25  Guidance Laboratory Inc.
Email:webmaster1g.yi.org Hits:0 Last modified:2013-06-19 07:53:36