posts - 36, comments - 30, trackbacks - 0, articles - 0

A:http://zlib.net/                                                               zlib1.2.3
B:http://www.info-zip.org/                                               zipUtil

C:引自http://www.cppblog.com/artmouse/archive/2005/12/13/1705.html
1说能用在wince里面的了,但是好像用起来烦了点
http://www.codeproject.com/file/zip_utils.asp
 2还有一个是国产的,但是wince里面用不了,
http://www.vckbase.com/document/viewdoc/?id=1265


zip_util:

Example 1 - create a Zip file from existing files


// We place the file "simple.bmp" inside, but inside
  // the zipfile it will actually be called "znsimple.bmp".
  // Similarly the textfile.

  HZIP hz = CreateZip("simple1.zip",0);
  ZipAdd(hz,"znsimple.bmp",  "simple.bmp");
  ZipAdd(hz,"znsimple.txt",  "simple.txt");
  CloseZip(hz);
 

Example 2 - unzip a Zip file using the names it has inside it

  HZIP hz = OpenZip("\\simple1.zip",0);
ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index;
// -1 gives overall information about the zipfile
for (int zi=0; zi<numitems; zi++)
{ ZIPENTRY ze; GetZipItem(hz,zi,&ze); // fetch individual details
UnzipItem(hz, zi, ze.name);         // e.g. the item's name.
}
CloseZip(hz);

Example 3- unzip from resource directly into memory

HRSRC hrsrc = FindResource(hInstance,MAKEINTRESOURCE(1),RT_RCDATA);
  HANDLE hglob = LoadResource(hInstance,hrsrc);
  void *zipbuf = LockResource(hglob);
  unsigned int ziplen = SizeofResource(hInstance,hrsrc);
  hz = OpenZip(zipbuf, ziplen, 0);
  ZIPENTRY ze; int i; FindZipItem(hz,"sample.jpg",true,&i,&ze);
  // that lets us search for an item by filename.
  // Now we unzip it to a membuffer.
  char *ibuf = new char[ze.unc_size];
  UnzipItem(hz,i, ibuf, ze.unc_size);
  ...
  delete[] ibuf;
  CloseZip(hz);
  // note: no need to free resources obtained through Find/Load/LockResource

Example 4 - unzip chunk by chunk to a membuffer

char buf[1024]; ZRESULT zr=ZR_MORE; unsigned long totsize=0;
  while (zr==ZR_MORE)
  { zr = UnzipItem(hz,i, buf,1024);
    unsigned long bufsize=1024; if (zr==ZR_OK) bufsize=ze.unc_size-totsize;
    ... maybe write the buffer to a disk file here
    totsize+=bufsize;
  }

zlib1.2.3

1:compress和uncompress:压缩和解压
compress(&out,&outlen,in,inlen);
2:gz file:
gzopen,gzseek,gzclose,gztell
写入gz: gzputc单个字符,gzputs字符串,gzprintf以format的方式写入.
读取gz:gzread,gzgetc,gzungetc(把前边的字符变成c),gzgets
3:deflate算法是先利用LZ77压缩后用Huffman在压缩的
deflateInit_,deflate,deflateEnd,deflateParams
inflateInit,inflate,inflateEnd
inflateSync,deflateSetDictionary,inflateSetDictionary



void test_compress(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    int err;
    uLong len = (uLong)strlen(hello)+1;

    err = compress(compr, &comprLen, (const Bytef*)hello, len);
    CHECK_ERR(err, "compress");

    strcpy((char*)uncompr, "garbage");

    err = uncompress(uncompr, &uncomprLen, compr, comprLen);
    CHECK_ERR(err, "uncompress");

    if (strcmp((char*)uncompr, hello)) {
        fprintf(stderr, "bad uncompress\n");
        exit(1);
    } else {
        printf("uncompress(): %s\n", (char *)uncompr);
    }
}

/* ===========================================================================
 * Test read/write of .gz files
 */
void test_gzio(fname, uncompr, uncomprLen)
    const char *fname; /* compressed file name */
    Byte *uncompr;
    uLong uncomprLen;
{
#ifdef NO_GZCOMPRESS
    fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
#else
    int err;
    int len = (int)strlen(hello)+1;
    gzFile file;
    z_off_t pos;

    file = gzopen(fname, "wb");
    if (file == NULL) {
        fprintf(stderr, "gzopen error\n");
        exit(1);
    }
    gzputc(file, 'h');
    if (gzputs(file, "ello") != 4) {
        fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
        exit(1);
    }
    if (gzprintf(file, ", %s!", "hello") != 8) {
        fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
        exit(1);
    }
    gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
    gzclose(file);

    file = gzopen(fname, "rb");
    if (file == NULL) {
        fprintf(stderr, "gzopen error\n");
        exit(1);
    }
    strcpy((char*)uncompr, "garbage");

    if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
        fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
        exit(1);
    }
    if (strcmp((char*)uncompr, hello)) {
        fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
        exit(1);
    } else {
        printf("gzread(): %s\n", (char*)uncompr);
    }

    pos = gzseek(file, -8L, SEEK_CUR);
    if (pos != 6 || gztell(file) != pos) {
        fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
                (long)pos, (long)gztell(file));
        exit(1);
    }

    if (gzgetc(file) != ' ') {
        fprintf(stderr, "gzgetc error\n");
        exit(1);
    }

    if (gzungetc(' ', file) != ' ') {
        fprintf(stderr, "gzungetc error\n");
        exit(1);
    }

    gzgets(file, (char*)uncompr, (int)uncomprLen);
    if (strlen((char*)uncompr) != 7) { /* " hello!" */
        fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
        exit(1);
    }
    if (strcmp((char*)uncompr, hello + 6)) {
        fprintf(stderr, "bad gzgets after gzseek\n");
        exit(1);
    } else {
        printf("gzgets() after gzseek: %s\n", (char*)uncompr);
    }

    gzclose(file);
#endif
}

posted @ 2007-10-11 11:36 vcommon 阅读(1271) | 评论 (0)编辑 收藏

 
Home Software Win32 Tutorials Sourcecode and Snippets Links to other sites About Catch22

Win32 Tips and Tricks

Introduction

This section presents a few win32 programming tips that I have picked up whilst learning to program Windows. Please select a topic from the list below.

  1. Filling areas with a solid colour
  2. Dragging a window by its client area
  3. Get the mouse position at any time
  4. Automatically link in a library from a source-level command
  5. Calculate the point size of a font
  6. Prevent a window from being resized
  7. Change the colours of an Edit control
  8. Center a window relative to its parent
  9. Prevent a Rebar's text labels from flickering
  10. Create non-rectangular windows
  11. Update the text in a status bar
  12. Display the customize dialog for a toolbar
  13. Resize a window without having to move it as well
  14. Give a Rebar control a double-gripper
  15. Calculate the size of a menu bar
  16. Share data between multiple processes
  17. Detect when the mouse has left a window
  18. Undocumented flags for GetDCEx
  19. Generate messages during compile time
  20. Undocumented Visual C stuff

Filling areas with a solid colour

The ExtTextOut API call is the fastest and simplest way to fill a rectangular area with a solid colour. Most people are aware of the FillRect API call. The disadvantage of this function is that it requires the user to supply a handle to a brush, which also means that you must look after this brush yourself. PatBlt is another fast way to fill an area with a brush, but has the same inconveniences as FillRect.

By using the ETO_OPAQUE flag in the call to ExtTextOut, and supplying a zero-length string to display, you can quickly and easily fill a rectangular area using the current background colour.


void PaintRect(HDC hdc, RECT *rect, COLORREF colour)
{
COLORREF oldcr = SetBkColor(hdc, colour);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, rect, "", 0, 0);
SetBkColor(hdc, oldcr);
}

Dragging a window by its client area

The simplest way to drag a window by its client area (or drag a window if it has no title bar), is to handle the WM_NCHITTEST message that is sent to every window when a mouse event occurs.
By returning a value of HTCAPTION from the WM_NCHITTEST message handler, you can fool windows into thinking that the mouse is over a caption bar, and the window can be dragged around with the mouse. It is best to only allow dragging by the client area of a window - otherwise, the window borders would become unusable. To achieve this, call the default window procedure, and check if its return value is HTCLIENT - if it is, then return HTCAPTION instead. Otherwise, just let the default behaviour take place.

UINT uHitTest;
...
case WM_NCHITTEST:
uHitTest = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam);
if(uHitTest == HTCLIENT)
return HTCAPTION;
else
return uHitTest;

Get the mouse position at any time

The current mouse position can always be retrieved with a call to GetCursorPos. However, the API call GetMessagePos returns the mouse position at the time when the last message was posted.


Automatically include a library from a source file (Visual C)

Including the following command in any source file will include a library search record in the resulting object file, which when it comes to link time, will ensure that the specified file will always be included.

#pragma comment( lib, "filename.lib" );


Calculate the point size of a font

The LOGFONT structure specifies the a fontsize in logical units, which is fairly useless in alot of cases. Alot of the time "points" are useful for displaying the size of a font in a user-interface. Use the following formula to convert from logical units to points, when using the MM_TEXT mapping mode.

int pointsize = MulDiv(logheight, 72, GetDeviceCaps(hdc, LOGPIXELSY));

To convert from points back to logical device coordinates, use

int logheight = -MulDiv(pointsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);

Prevent a window from being resized

There are three ways to prevent a window from being resized.

1. Make sure the window does not have the WS_THICKFRAME style set, as this allows the user to resize the window.
2. Handle the WM_GETMINMAXINFO message.
3. Handle the WM_SIZING message.


Change the colours of an EDIT control

The best way to change the colours of an edit control is to handle the WM_CTLCOLOREDIT message in the parent window of the edit control. When you receive this message, you will have the device context in wParam. You can use SetTextColor and SetBkColor on this device context to set the colours. Lastly, you must return a handle to a brush (which you must assume ownership of), which is used to paint the edit control's background.

case WM_CTLCOLOREDIT:
hdc = (HDC)wParam;
SetTextColor(hdc, RGB(255,0,0));            // red
SetBkColor(hdc, RGB(255,255,0));            // yellow
return GetSysColorBrush(COLOR_3DHILIGHT);   // hilight colour

Center a window relative to its parent

Here's a quick and easy method to center any window relative to its parent window.

BOOL CenterWindow(HWND hwnd)
{
HWND hwndParent;
RECT rect, rectP;
int width, height;
int screenwidth, screenheight;
int x, y;
//make the window relative to its parent
hwndParent = GetParent(hwnd);
GetWindowRect(hwnd, &rect);
GetWindowRect(hwndParent, &rectP);
width  = rect.right  - rect.left;
height = rect.bottom - rect.top;
x = ((rectP.right-rectP.left) -  width) / 2 + rectP.left;
y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top;
screenwidth  = GetSystemMetrics(SM_CXSCREEN);
screenheight = GetSystemMetrics(SM_CYSCREEN);
//make sure that the dialog box never moves outside of
//the screen
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x + width  > screenwidth)  x = screenwidth  - width;
if(y + height > screenheight) y = screenheight - height;
MoveWindow(hwnd, x, y, width, height, FALSE);
return TRUE;
}

Prevent a Rebar's text labels from flickering

A rebar control is usually contained within the top portion of a main window. Whenever the main window's size changes, the rebar must also be resized to fit. The obvious way to do this is to handle WM_SIZE, and use MoveWindow(0, 0, width, rebar_height) to size the rebar exactly. However, this causes the text labels on a rebar control to flicker. To prevent this from happening, size the rebar control to the cover total size of the main window's client area. The rebar has some special sizing logic inside it which stretches the rebar across its parent's width, but keeps its height constant, even though you told it to be stretched vertically as well. Believe it or not, this works:

In the main window's WM_SIZE handler:

case WM_SIZE:
MoveWindow(hwndRebar, 0, 0, LOWORD(lParam), HIWORD(lParam));
...

Create non-rectangular windows

The SetWindowRgn API can be used to give any window a non-rectangular shape. A region must be created, using any of the Region functions, such as CreateRectRgn or CreateEllipticRgn. The region coordinates must be window-relative.

HRGN hrgn;
...
hrgn = CreateEllipticRgn(0, 0, 100, 100);
SetWindowRgn(hwnd, hrgn, TRUE);

Update the text in a status bar

Here's a useful function to set the text of any status bar pane using a printf-like call

#include <stdarg.h>
/* style can be SBT_NOBORDERS etc */
void SetStatusBarText(HWND hwndSB, int part, unsigned style, char *fmt, ...)
{
char tmpbuf[128];
va_list argp;
va_start(argp, fmt);
_vsnprintf(tmpbuf, sizeof(tmpbuf), fmt, argp);
va_end(argp);
//cannot use PostMessage, as the panel type is not set correctly
SendMessage(hwndSB, SB_SETTEXT, (WPARAM)part | style, (LPARAM)(LPSTR)tmpbuf);
}

Display the Customize dialog for a toolbar

The standard windows customization dialog for toolbars can be displayed by sending the toolbar the TB_CUSTOMIZE message.

SendMessage(hwndToolbar, TB_CUSTOMIZE, 0, 0);

You must remember to handle the TBN_QUERYDELETE and TBN_QUERYINSERT notifications, and return non-zero for both of these. Without them, the customize dialog will appear very briefly and then vanish.


Resize a window without having to move it

The easiest way to resize or move a window is to use the MoveWindow API. There is another function though, SetWindowPos, which can be used just to resize a window, and to keep it in the same place, by specifying the appropriate flags.

void SizeWindow(HWND hwnd, int width, int height)
{
SetWindowPos(hwnd, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
}

Give a Rebar control a double gripper

Does anyone else prefer the rebar controls that Internet Explorer 3 had? The ones with the double-grippers? There is an easy way to give the newer rebar controls (single-grippers) a new look, by using the custom draw feature that all common controls support.

You must create the rebar's bands with the RBBS_GRIPPERALWAYS style (to display the single vertical grip bar). You must also set each rebar band's header size to around 10 pixels to allow extra room for the addtional gripper.

REBARBANDINFO rbBand;
...
rbBand.cbSize   = sizeof(REBARBANDINFO);
rbBand.fMask    = RBBIM_STYLE | RBBIM_HEADERSIZE /* include the others here */;
rbBand.fStyle   = RBBS_NOVERT | RBBS_CHILDEDGE | RBBS_GRIPPERALWAYS;
rbBand.cxHeader = 10;

Handle the WM_NOTIFY message in the rebar control's parent window. When you receive a NM_CUSTOMDRAW notification for your rebar, use the following function to draw the extra gripper:

LRESULT RebarCustomDraw(NMCUSTOMDRAW *lpcd)
{
RECT rect;
if(lpcd->dwDrawStage == CDDS_PREPAINT)
{
return CDRF_NOTIFYPOSTPAINT;
}
else if(lpcd->dwDrawStage == CDDS_POSTPAINT && lpcd->dwItemSpec != 0)
{
SetRect(&rect, 5, 2, 8, 38);
DrawEdge(lpcd->hdc, &rect, BDR_RAISEDINNER, BF_RECT|BF_LEFT|BF_RIGHT);
return 0;
}
return CDRF_DODEFAULT;
}

Calculate the size of a menu bar

It is straight-forward to calculate the size of a menu bar, or even a drop-down menu. You can use the GetMenuItemRect function (available in all 32bit versions of Windows) to work out the size of each item, and then use a loop to add all of the individual items together to work out the size of the whole menu.

BOOL GetMenuRect(HWND hwnd, HMENU hmenu, RECT *pmenurect)
{
RECT rect;
int  i;
SetRect(pmenurect, 0, 0, 0, 0);
for(i = 0; i < GetMenuItemCount(hmenu); i++)
{
GetMenuItemRect(hwnd, hmenu, i, &rect);
UnionRect(pmenurect, pmenurect, &rect);
}
return TRUE;
}

Share data between multiple processes (Windows NT)

The simplest way to share data between multiple instances of the same program is to create a new section in the executable. You must use a some form of protected access to the variable to prevent threading problems.

// Instruct compiler to put g_SharedVariable in its own section,
// so it can be shared amongst multiple instances
#pragma data_seg("Shared")
LONG g_SharedVariable = -1;
#pragma data_seg()
#pragma comment(linker, "/section:Shared,rws")

Detect when the mouse has left a window

There are four ways to detect when the mouse has left a window

1. Use the TrackMouseEvent API and the WM_MOUSELEAVE message (Win98/NT4+)

2. By using SetCapture API. When the window first receives a WM_MOUSEMOVE message, set the mouse capture. When the mouse leaves the window, Windows will send the window one last WM_MOUSEMOVE (the coordinates will be outside the window's client area). You can use this fact to detect when the mouse has left a window.

3 . By using a Timer. When the mouse enters a window, set a timer going with a small interval (10ms, say). When the timer expires, check if the mouse is still in the window. If it is, then let the timer keep going. Otherwise, the mouse has left the window, and the timer can be stopped.

4 . By using a mouse hook. When the mouse enters a window, install a mouse hook to monitor all mouse events. By checking for WM_MOUSEMOVE messages, you can check when the mouse has left a window and remove the hook appropriately.


Undocumented flags for GetDCEx

(Curtesy of Feng Yuan) GetDCEx can be used to retrieve the device context for a window during processing of WM_NCPAINT. The documentation states that this is achieved by using

GetDCEx(hwnd, hrgn, DCX_WINDOW | DCX_INTERSECTRGN);


However, this call never works, because there is an undocumented flag to include which is not mentioned anywhere.

GetDCEx(hwnd, hrgn, DCX_WINDOW | DCX_INTERSECTRGN | 0x10000);

Generate messages during compile time

It is possible to produce messages in the compilation window when a certain line of source code is compiled. This can be very useful, as you can leave reminders or warnings that a certain section of code may need reviewing. Use the following #pragma statement to create a message to yourself whenever the source file is compiled:

#pragma MESSAGE(Add error checking here later);

This is the macro itself. Place this in a header file and include it in any source file that you want to include this message capability for.

#define chMSG(x)   #x
#define chMSG2(x)  chMSG(x)
#define MESSAGE(desc) message(__FILE__ "(" chMSG2(__LINE__) ") : message : " #desc)

Undocumented Visual C stuff

You can display x number of elements in the watch window, by specifying a number after the variable name.
e.g. plist, 15 will display 15 elements of the array pointed to by plist (assuming plist is a pointer).



Please send any comments or suggestions to: james@catch22.net

Last modified: 10 October 2005 22:38:07

posted @ 2007-09-15 16:05 vcommon 阅读(463) | 评论 (0)编辑 收藏

1:IME
控制IME,超多函数。
ImmSetCompositionWindow,ImmSetCandidateWindow,ImmGetContext.......简单如下流程:
当WM_IME_COMPOSITION时,ImmGetContext,ImmGetCompositionString,得到输入内容显示,
收到 IMN_CHANGECANDIDATE消息时,用ImmGetCandidateList得到选字表。
自定义IME时,自己得到内容显示和字表,以自己的风格显示。

比如打yiren,ImmGetCompositionString--GCS_COMPREADSTR就是yi ren,GCS_COMPSTR就是一人
比如wo,ImmGetCandidateList会得到我,沃,握......


2:

posted @ 2007-09-15 15:55 vcommon 阅读(584) | 评论 (0)编辑 收藏

1:HookAPICalls()
利用PE的结构转向.


/*--------------------------------------------------------------------------------------------------------
    APIHIJACK.CPP - Based on DelayLoadProfileDLL.CPP, by Matt Pietrek for MSJ February 2000.
    http://msdn.microsoft.com/library/periodic/period00/hood0200.htm
    Adapted by Wade Brainerd, wadeb@wadeb.com
--------------------------------------------------------------------------------------------------------*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "apihijack.h"

//===========================================================================
// Called from the DLPD_IAT_STUB stubs.  Increments "count" field of the stub

void __cdecl DefaultHook( PVOID dummy )
{
    __asm   pushad  // Save all general purpose registers

    // Get return address, then subtract 5 (size of a CALL X instruction)
    // The result points at a DLPD_IAT_STUB

    // pointer math!  &dummy-1 really subtracts sizeof(PVOID)
    PDWORD pRetAddr = (PDWORD)(&dummy - 1);

    DLPD_IAT_STUB * pDLPDStub = (DLPD_IAT_STUB *)(*pRetAddr - 5);

    pDLPDStub->count++;

    #if 0
    // Remove the above conditional to get a cheezy API trace from
    // the loader process.  It's slow!
    if ( !IMAGE_SNAP_BY_ORDINAL( pDLPDStub->pszNameOrOrdinal) )
    {
        OutputDebugString( "Called hooked function: " );
        OutputDebugString( (PSTR)pDLPDStub->pszNameOrOrdinal );
        OutputDebugString( "\n" );
    }
    #endif

    __asm   popad   // Restore all general purpose registers
}

// This function must be __cdecl!!!
void __cdecl DelayLoadProfileDLL_UpdateCount( PVOID dummy );

PIMAGE_IMPORT_DESCRIPTOR g_pFirstImportDesc;

//===========================================================================
// Given an HMODULE, returns a pointer to the PE header

PIMAGE_NT_HEADERS PEHeaderFromHModule(HMODULE hModule)
{
    PIMAGE_NT_HEADERS pNTHeader = 0;
   
    __try
    {
        if ( PIMAGE_DOS_HEADER(hModule)->e_magic != IMAGE_DOS_SIGNATURE )
            __leave;

        pNTHeader = PIMAGE_NT_HEADERS(PBYTE(hModule)
                    + PIMAGE_DOS_HEADER(hModule)->e_lfanew);
       
        if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
            pNTHeader = 0;
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {      
    }

    return pNTHeader;
}

//===========================================================================
// Builds stubs for and redirects the IAT for one DLL (pImportDesc)

bool RedirectIAT( SDLLHook* DLLHook, PIMAGE_IMPORT_DESCRIPTOR pImportDesc, PVOID pBaseLoadAddr )
{
    PIMAGE_THUNK_DATA pIAT;     // Ptr to import address table
    PIMAGE_THUNK_DATA pINT;     // Ptr to import names table
    PIMAGE_THUNK_DATA pIteratingIAT;

    // Figure out which OS platform we're on
    OSVERSIONINFO osvi;
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    GetVersionEx( &osvi );

    // If no import names table, we can't redirect this, so bail
    if ( pImportDesc->OriginalFirstThunk == 0 )
        return false;

    pIAT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->FirstThunk );
    pINT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->OriginalFirstThunk );

    // Count how many entries there are in this IAT.  Array is 0 terminated
    pIteratingIAT = pIAT;
    unsigned cFuncs = 0;
    while ( pIteratingIAT->u1.Function )
    {
        cFuncs++;
        pIteratingIAT++;
    }

    if ( cFuncs == 0 )  // If no imported functions, we're done!
        return false;

    // These next few lines ensure that we'll be able to modify the IAT,
    // which is often in a read-only section in the EXE.
    DWORD flOldProtect, flNewProtect, flDontCare;
    MEMORY_BASIC_INFORMATION mbi;
   
    // Get the current protection attributes                           
    VirtualQuery( pIAT, &mbi, sizeof(mbi) );
   
    // remove ReadOnly and ExecuteRead attributes, add on ReadWrite flag
    flNewProtect = mbi.Protect;
    flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);
    flNewProtect |= (PAGE_READWRITE);
   
    if ( !VirtualProtect(   pIAT, sizeof(PVOID) * cFuncs,
                            flNewProtect, &flOldProtect) )
    {
        return false;
    }

    // If the Default hook is enabled, build an array of redirection stubs in the processes memory.
    DLPD_IAT_STUB * pStubs = 0;
    if ( DLLHook->UseDefault )
    {
        // Allocate memory for the redirection stubs.  Make one extra stub at the
        // end to be a sentinel
        pStubs = new DLPD_IAT_STUB[ cFuncs + 1];
        if ( !pStubs )
            return false;
    }

    // Scan through the IAT, completing the stubs and redirecting the IAT
    // entries to point to the stubs
    pIteratingIAT = pIAT;

    while ( pIteratingIAT->u1.Function )
    {
        void* HookFn = 0;  // Set to either the SFunctionHook or pStubs.

        if ( !IMAGE_SNAP_BY_ORDINAL( pINT->u1.Ordinal ) )  // import by name
        {
            PIMAGE_IMPORT_BY_NAME pImportName = MakePtr( PIMAGE_IMPORT_BY_NAME, pBaseLoadAddr, pINT->u1.AddressOfData );

            // Iterate through the hook functions, searching for this import.
            SFunctionHook* FHook = DLLHook->Functions;
            while ( FHook->Name )
            {
                if ( lstrcmpi( FHook->Name, (char*)pImportName->Name ) == 0 )
                {
                    OutputDebugString( "Hooked function: " );
                    OutputDebugString( (char*)pImportName->Name );
                    OutputDebugString( "\n" );

                    // Save the old function in the SFunctionHook structure and get the new one.
                    FHook->OrigFn = reinterpret_cast<void*>(pIteratingIAT->u1.Function);
                    HookFn = FHook->HookFn;
                    break;
                }

                FHook++;
            }

            // If the default function is enabled, store the name for the user.
            if ( DLLHook->UseDefault )
                pStubs->pszNameOrOrdinal = (DWORD)&pImportName->Name;
        }
        else
        {
            // If the default function is enabled, store the ordinal for the user.
            if ( DLLHook->UseDefault )
                pStubs->pszNameOrOrdinal = pINT->u1.Ordinal;
        }

        // If the default function is enabled, fill in the fields to the stub code.
        if ( DLLHook->UseDefault )
        {
            pStubs->data_call = (DWORD)(PDWORD)DLLHook->DefaultFn
                                - (DWORD)(PDWORD)&pStubs->instr_JMP;
            pStubs->data_JMP = *(PDWORD)pIteratingIAT - (DWORD)(PDWORD)&pStubs->count;

            // If it wasn't manually hooked, use the Stub function.
            if ( !HookFn )
                HookFn = (void*)pStubs;
        }

        // Replace the IAT function pointer if we have a hook.
        if ( HookFn )
        {
            // Cheez-o hack to see if what we're importing is code or data.
            // If it's code, we shouldn't be able to write to it
            if ( IsBadWritePtr( (PVOID)pIteratingIAT->u1.Function, 1 ) )
            {
                pIteratingIAT->u1.Function = reinterpret_cast<DWORD>(HookFn);
            }
            else if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
            {
                // Special hack for Win9X, which builds stubs for imported
                // functions in system DLLs (Loaded above 2GB).  These stubs are
                // writeable, so we have to explicitly check for this case
                if ( pIteratingIAT->u1.Function > 0x80000000 )
                    pIteratingIAT->u1.Function = reinterpret_cast<DWORD>(HookFn);
            }
        }

        if ( DLLHook->UseDefault )
            pStubs++;           // Advance to next stub

        pIteratingIAT++;    // Advance to next IAT entry
        pINT++;             // Advance to next INT entry
    }

    if ( DLLHook->UseDefault )
        pStubs->pszNameOrOrdinal = 0;   // Final stub is a sentinel

    // Put the page attributes back the way they were.
    VirtualProtect( pIAT, sizeof(PVOID) * cFuncs, flOldProtect, &flDontCare);
   
    return true;
}

//===========================================================================
// Top level routine to find the EXE's imports, and redirect them
bool HookAPICalls( SDLLHook* Hook )
{
    if ( !Hook )
        return false;

    HMODULE hModEXE = GetModuleHandle( 0 );

    PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule( hModEXE );
   
    if ( !pExeNTHdr )
        return false;

    DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory
                        [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    if ( !importRVA )
        return false;

    // Convert imports RVA to a usable pointer
    PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr( PIMAGE_IMPORT_DESCRIPTOR,
                                                    hModEXE, importRVA );

    // Save off imports address in a global for later use
    g_pFirstImportDesc = pImportDesc;  

    // Iterate through each import descriptor, and redirect if appropriate
    while ( pImportDesc->FirstThunk )
    {
        PSTR pszImportModuleName = MakePtr( PSTR, hModEXE, pImportDesc->Name);

        if ( lstrcmpi( pszImportModuleName, Hook->Name ) == 0 )
        {
            OutputDebugString( "Found " );
            OutputDebugString( Hook->Name );
            OutputDebugString( "...\n" );

            RedirectIAT( Hook, pImportDesc, (PVOID)hModEXE );
        }
       
        pImportDesc++;  // Advance to next import descriptor
    }

    return true;
}

 

posted @ 2007-09-07 15:30 vcommon 阅读(1119) | 评论 (0)编辑 收藏

 注:1:一般使用多个窗口,都觉得对应一个device比较好做,但是这样一来,texture,vertex....在不同device之间不能共享,造成很大的浪费.
2: SetViewport是个重点.

#include "windows.h"
#include "d3d9.h"
#include "d3dx9.h"

#ifdef _DEBUG
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9d.lib")
#else
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#endif

HINSTANCE g_3DhInst;
ATOM g_3DWinClass;
HWND g_3DWindow=0;
HWND g_3DFocusWindow=0;
DWORD g_3DWindowStyleWin;
DWORD g_3DWindowStyleFullScreen;
DWORD g_3DWindowStyleExWin;
DWORD g_3DWindowStyleExFullScreen;
D3DPRESENT_PARAMETERS g_d3dpp;
LPDIRECT3D9 g_pD3D=0;
LPDIRECT3DDEVICE9 g_pDev=0;
bool g_bResetDevice = false;
char g_strWinClass[] = "QuickDX9";
char g_strWinTitle[] = "TestApp";

LRESULT WINAPI TestWinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 if (msg==WM_CLOSE)
 {
  PostQuitMessage(0);
 }
 else if (msg==WM_SIZE)
 {
  g_bResetDevice = true;
 }
 else if (msg==WM_KEYDOWN && wParam == VK_ESCAPE)
 {
  PostQuitMessage(0);
 }
 return DefWindowProc(hWnd, msg, wParam, lParam);
}

bool RegisterWin()
{
 WNDCLASSEX wndclass;

 memset(&wndclass, 0, sizeof(wndclass));
 wndclass.cbSize = sizeof(WNDCLASSEX);
 wndclass.style = CS_OWNDC;
 wndclass.lpfnWndProc = TestWinProc;
 wndclass.hInstance = g_3DhInst;
 wndclass.lpszClassName = g_strWinClass;
 g_3DWinClass = RegisterClassEx(&wndclass);
 return g_3DWinClass != 0;
}

bool CreateWin()
{
 RECT rc;

 g_3DWindowStyleFullScreen = g_3DWindowStyleWin = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
 g_3DWindowStyleExFullScreen = g_3DWindowStyleExWin = WS_EX_OVERLAPPEDWINDOW;
 rc.left = 0;
 rc.top = 0;
 rc.right = 800;
 rc.bottom = 600;
 AdjustWindowRectEx(&rc, g_3DWindowStyleWin, false, g_3DWindowStyleExWin);
 g_3DFocusWindow = CreateWindowEx(g_3DWindowStyleExWin, g_strWinClass, g_strWinTitle, g_3DWindowStyleWin,

0, 0, rc.right - rc.left, rc.bottom - rc.top, 0, 0, g_3DhInst, 0);
 g_3DWindow = g_3DFocusWindow;
 return g_3DWindow != 0;
}

bool MsgPump()
{
 MSG msg;
 static bool exit = false;

 if (exit)
  return false;

 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
 {
  if (msg.message == WM_QUIT)
  {
   exit = true;
   return false;
  }
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }
 return true;
}

void Cleanup()
{
 if (g_pDev)
  g_pDev->Release();
 if (g_pD3D)
  g_pD3D->Release();
 if (g_3DWindow)
  DestroyWindow(g_3DWindow);
}


bool CreateD3D()
{
 g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
 return g_pD3D != 0;
}

bool CreateDevice()
{
 RECT rc;

 GetClientRect(g_3DWindow, &rc);
 memset(&g_d3dpp, 0, sizeof(g_d3dpp));
 g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
 g_d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
 g_d3dpp.EnableAutoDepthStencil = true;
 g_d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
 g_d3dpp.hDeviceWindow = g_3DWindow;
 g_d3dpp.BackBufferWidth = rc.right - rc.left;
 g_d3dpp.BackBufferHeight = rc.bottom - rc.top;
 g_d3dpp.BackBufferCount = 1;
 g_d3dpp.Windowed = true;
 g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ;
 if (FAILED(g_pD3D->CreateDevice(0, D3DDEVTYPE_HAL, g_3DFocusWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING,

&g_d3dpp, &g_pDev)))
  return false;
 return true;
}

void TestPreReset();
bool TestPostReset();

bool ResetDevice()
{
 TestPreReset();
 if (FAILED(g_pDev->Reset(&g_d3dpp)))
  return false;
 return TestPostReset();
}

bool TestDevice()
{
 HRESULT hr = g_pDev->TestCooperativeLevel();

 if (hr == D3DERR_DEVICENOTRESET || (hr == S_OK && g_bResetDevice))
 {
  g_bResetDevice = false;
  if (!ResetDevice())
   return false;
 }
 else if (hr == D3DERR_DEVICELOST)
  return false;

 return true;
}

HWND g_swapwnd = 0;
LPDIRECT3DSWAPCHAIN9 g_pSwap = 0;
D3DPRESENT_PARAMETERS g_scparam;
LPDIRECT3DSURFACE9 g_pSwapDepthSurf = 0;
LPDIRECT3DSURFACE9 g_pSwapRenderSurf = 0;

LPDIRECT3DSURFACE9 g_pDevDepthSurf = 0;
LPDIRECT3DSURFACE9 g_pDevRenderSurf = 0;

bool TestSetup()
{
 RECT rc;
 rc.left = 0;
 rc.top = 0;
 rc.right = 400;
 rc.bottom = 400;
 AdjustWindowRectEx(&rc, g_3DWindowStyleWin, false, g_3DWindowStyleExWin);
 g_swapwnd = CreateWindowEx(g_3DWindowStyleExWin, g_strWinClass, "ChainWnd", g_3DWindowStyleWin, 800, 0,

rc.right - rc.left, rc.bottom - rc.top, 0, 0, g_3DhInst, 0);

 return TestPostReset();
}

void TestCleanup()
{
 TestPreReset();
 if (g_swapwnd)
  DestroyWindow(g_swapwnd);
}

void TestPreReset()
{
 if (g_pSwapDepthSurf)
  g_pSwapDepthSurf->Release();
 g_pSwapDepthSurf = 0;
 if (g_pSwapRenderSurf)
  g_pSwapRenderSurf->Release();
 g_pSwapRenderSurf = 0;
 if (g_pSwap)
  g_pSwap->Release();
 g_pSwap = 0;
 if (g_pDevRenderSurf)
  g_pDevRenderSurf->Release();
 g_pDevRenderSurf = 0;
 if (g_pDevDepthSurf)
  g_pDevDepthSurf->Release();
 g_pDevDepthSurf = 0;
}

bool TestPostReset()
{
 memset(&g_scparam, 0, sizeof(g_scparam));
 g_scparam.BackBufferCount = 1;
 g_scparam.BackBufferFormat = D3DFMT_X8R8G8B8;
 g_scparam.BackBufferHeight = 400;
 g_scparam.BackBufferWidth = 400;
 g_scparam.hDeviceWindow = g_swapwnd;
 g_scparam.SwapEffect = D3DSWAPEFFECT_DISCARD;
 g_scparam.Windowed = true;
 g_scparam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
 g_pDev->CreateAdditionalSwapChain(&g_scparam, &g_pSwap);
 g_pSwap->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &g_pSwapRenderSurf);
 g_pDev->CreateDepthStencilSurface(400,400,D3DFMT_D24X8, D3DMULTISAMPLE_NONE, 0, false, &g_pSwapDepthSurf,

0);

 g_pDev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &g_pDevRenderSurf);
 g_pDev->GetDepthStencilSurface(&g_pDevDepthSurf);
 return true;
}

class TestVert
{
public:
 float x,y,z;
 DWORD color;
};

TestVert g_aoVerts[4];
D3DXMATRIX w,v,p;

void TestUpdate()
{
 g_aoVerts[0].x = -1;
 g_aoVerts[0].y = -1;
 g_aoVerts[0].z =  0;
 g_aoVerts[0].color = 0xFFFF0000;

 g_aoVerts[1].x = -1;
 g_aoVerts[1].y =  1;
 g_aoVerts[1].z =  0;
 g_aoVerts[1].color = 0xFFFFFF00;

 g_aoVerts[2].x =  1;
 g_aoVerts[2].y = -1;
 g_aoVerts[2].z =  0;
 g_aoVerts[2].color = 0xFFFF00FF;

 g_aoVerts[3].x =  1;
 g_aoVerts[3].y =  1;
 g_aoVerts[3].z =  0;
 g_aoVerts[3].color = 0xFFFFFFFF;

 POINT pt;
 GetCursorPos(&pt);
 D3DXMatrixRotationYawPitchRoll(&w, (pt.x - 800.0f) / 800 * D3DX_PI / 2, (pt.y - 600.0f) / 600 * D3DX_PI /

2, 0);

 w._43 = 2;
 D3DXMatrixPerspectiveFovLH(&p, D3DX_PI/4, 1.0, 0.1f, 500.0f);

 g_pDev->SetTransform(D3DTS_WORLD, &w);
 g_pDev->SetTransform(D3DTS_PROJECTION, &p);
 D3DXMatrixIdentity(&w);
 g_pDev->SetTransform(D3DTS_VIEW, &w);
}

void TestRender()
{
 g_pDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
 g_pDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
 g_pDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
 g_pDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);

 g_pDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
 g_pDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);

 g_pDev->SetRenderState(D3DRS_LIGHTING, false);

 g_pDev->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE);
 g_pDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
 g_pDev->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_aoVerts, sizeof(TestVert));
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdLine, int cmdShow)
{

 g_3DhInst = hInst;
 do
 {
  if (!RegisterWin())
   break;
  if (!CreateWin())
   break;
  if (!CreateD3D())
   break;
  if (!CreateDevice())
   break;
  if (!TestSetup())
   break;
  while (MsgPump())
  {
   if (TestDevice())
   {
    D3DVIEWPORT9 vp;

    vp.X = 0;
    vp.Y = 0;
    vp.Width = 800;
    vp.Height = 600;
    vp.MinZ = 0;
    vp.MaxZ = 1;
    TestUpdate();
    g_pDev->SetRenderTarget(0, g_pDevRenderSurf);
    g_pDev->SetDepthStencilSurface(g_pDevDepthSurf);
    g_pDev->SetViewport(&vp);
    g_pDev->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x456789, 1.0f, 0);
    g_pDev->BeginScene();
    TestRender();
    g_pDev->EndScene();
    g_pDev->Present(0,0,0,0);

    g_pDev->SetRenderTarget(0, g_pSwapRenderSurf);
    g_pDev->SetDepthStencilSurface(g_pSwapDepthSurf);
    vp.Width = 400;
    vp.Height = 400;
    g_pDev->SetViewport(&vp);
    g_pDev->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x654321, 1.0f, 0);
    g_pDev->BeginScene();
    TestRender();
    g_pDev->EndScene();
    g_pSwap->Present(0, 0, 0, 0, 0);
   }
  };
 } while (0);

 TestCleanup();
 Cleanup();

 return 0;
}

 

 

posted @ 2007-09-07 15:07 vcommon 阅读(1145) | 评论 (0)编辑 收藏

16:使用sprite写字,没有Disable Z buffer,D3DRS_ZWRITEENABLE.
结果出现了ERROR_SECTOR_NOT_FOUND的错误.
写字流程--SetRenderTarget,Sprite->Begin,Sprite->End

15:StretchRect 总是失败.
结论.,必须是D3DUSAGE_RENDERTARGET和D3DPOOL_DEFAULT的texture.由于没有设置D3DUSAGE_RENDERTARGET,导致失败.

14: m_pSprite->Begin
如果字也alpha的话,很有可能出问题.字体模糊不清.

13:D3DXFilterTexture
D3DXFillTexture是一个简单的方式去FillTexture,但是不一定好用在大规模copy的地方。适合简单生成纹理。

12:D3DXLoadSurfaceFromMemory
如果surface是一个D3DPOOL_DEFAULT的话,这个函数比LockRect,一个字节一个字节的copy还慢。


11:SetRenderState( D3DRS_SRCBLENDALPHA,D3DBLEND_SRCALPHA);
SetRenderState( D3DRS_DESTBLENDALPHA , D3DBLEND_INVSRCALPHA  );是默认选项
不小心改成了
SetRenderState( D3DRS_SRCBLENDALPHA,D3DBLEND_SRCALPHA);
SetRenderState( D3DRS_DESTBLENDALPHA , D3DBLEND_DESTALPHA  );
后,发现和背景alpha的时候经常受背景影响,出现虚边和毛边。找了一天,终于找到原因。

10:DirectShow版本在VC6和VS2005上无法编译等原因.
#define POINTER_64 __ptr64

9:#define D3D_DEBUG_INFO

在最前

如果使用了stdafx.h,一定要Create Precompiled Header (/Yc)
如果使用Use Precompiled Header (/Yu),那么stdafx.h早已经include了d3d9.h,所以这个define其实一直都没有被加上.

在decontrol panel里打开d3d的debug,能看到更多的debug信息.大多是关于错误等信息的.

 8:stl 
map<string,string>然后发生:
include\functional(139) : error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::string'
原因少include<string>

 

7:performance:
  LARGE_INTEGER freq;
  BOOL ret = QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&counter_end);
int((counter_end.QuadPart-counter_start.QuadPart)/(freq.QuadPart/10000000))
//1000是ms

8:D3DXCreateTexture,create的height可能和设置的不一样,因为还要对齐。所以要用GetSurfaceLevel和GetDesc来得到他的宽高,然后填充,否则就会有花的一块。

7:disable lighting.如果没有disable,就必须要设置材质和贴图才能看到东东的贴图。

6:if(PeekMessage( &msg, NULL, 0, 0 ,PM_REMOVE) )的参数问题.
if(PeekMessage( &msg, Hwnd, 0, 0 ,PM_REMOVE) )将收不到很多消息如WM_QUIT。

5:Ogre
Ogre的font画是使用OverlayManager完成的.TextAreaOverlayElement,HardwareBuffer,D3D9HardwareVertexBuffer::lockImpl,mlpD3DBuffer->Lock.Ogre::Font最终依然使用FT_Load_Char来完成,将char转化Material。OverlayElement::_updateRenderQueue,const_cast<Renderable*>(rend)->getRenderOperation(ro);TextAreaOverlayElement::getRenderOperation,
setcapture("title"),其实是保存了一个RenderOperation,由render线程,scencemanger等获得并render.D3D9RenderSystem::_render(const RenderOperation& op),最后由hr = mpD3DDevice->DrawPrimitive画出三角形。TextAreaOverlayElement::initialise则是初始化这群三角形。hr = mpD3DDevice->SetStreamSource(static_cast<UINT>(VertexBufferBinding)

4:CEGUI
CEGUI的font画法也是使用FreeType字体库FreeTypeFont::rasterize来生成一个image的对象。FT_Load_Char,drawGlyphToBuffer完成了所有的工作。

3:ID3DXSprite和3D图形
ID3DXSprite自己是有排序的,所以画的时候有先后顺序.
但和3D融合不很好,不知道怎么把3D放到ID3DXSprite前边,估计不行.

2:WM_SIZE
窗口缩放的时候,分辨率不变,会引起失真.
所以在WM_SIZE的时候要m_pd3dDevice->Reset( &m_d3dpp );
m_d3dpp 使用最新的width和height就可以了.
但是所有的object都要重新分配,这就需要很多的工作了.

1: 鼠标选取。
D3DX有个方法D3DXIntersect,ogre也准许同样技巧

CompositorInstance::collectPasses
http://www.codercorner.com/Opcode.htm
OPCODE - Optimized Collision Detection
IntersectTriangle:

orginPoint + T*Dir = V1 + U*(V2-V1) + V*(V3-V1); 两边乘以 (v2 - v1) X (v3 - v1) 消去u, v ,就能解得T, 乘以 Dir X (V2 -v1) 计算 V, 乘以 Dir X (v2 - v1)!

the Above is relation function:
t(distance from intersct point to ray.p0)
u,v are barycentric coord!

so we have triangle plane : V = V0 + u * edge1 + v * edge2
and ray - line : P = orig + t * dir
so:
V0 + u * edge1 + v * edge2 = orig + t * dir

t = (V0 - orig)(edge1 X edge2) / dir * (edeg1 X edge2) // X is cross product
u = (orig - V0) * (dir X edge2) / edge1 * (dir X edge2)
v = (orig - V0) * (dir X edge1) / edge2 * (dir X edge1)

we make some tranform By below quation
A * (B X C) = B * (C X A ) = C * (A X B)

t = edge2 * ((orig - V0 ) X edge1) / edge1 * (dir X edge2)
u = (orig - v0) * (dir X edge2) / edge1 * (dir X edge2)
v = dir * ((orig - V0) X edge1) / edge1 * (dir X edge2)

so this equation we only need 2 cross product operation!

参考文献<<用OpenGL实现射线拣取对象程序设计>>
http://softsurfer.com/Archive/algorithm_0105/algorithm_0105.htm

×----×---
基础知识
计算两个3-D向量的点乘 D3DXVec3Dot
计算两个3-D向量叉乘 D3DXVec3Cross
点乘 abcosθ,所以=0,垂直
叉乘 x1/x2 = y1/y2 = z1/z2,平行

(叉乘ab)点乘c=0,共面

posted @ 2007-08-23 11:17 vcommon 阅读(3382) | 评论 (1)编辑 收藏

1:下载了ogre-win32-v1-4-3,OgreDependencies_VC8SP1_Eihort_20070503
加入dependency的include和lib之后编译成功,但是无法运行。报error,“应用程序正常初始化(0xc0150002)失败。”
查到还是manifest的原因,可能是vc8 beta1,beta2或platform sdk有关,根据调试时的提示,找到有问题的dll.CEGUIBase_d.dll,OIS_d.dll,OgreMain_d.dll.  去掉manifset, 重新编译CEGUIBase_d.dll。


3:ois-1.0RC1_Win32.zip,CEGUI-0.5.0b.zip,CEGUI-DEPS-0.5.0b-vc8.zip。
重新编译OIS_d.dll,CEGUIBase_d.dll。
编译OIS的时候默认是static的library,需要自己更改成DebugDll.
编译CEGUI的时候找不到.sln文件。搜到如下,在CEGUI-0.5.0\makefiles\premake下运行build_vs2005.bat,可自动生成.sln文件。
编译完成后替换到OgreDependencies_VC8SP1_Eihort_20070503里使用。

4:编译OGRE成功,但是运行crash.
ogre-win32-v1-4-3\ogrenew\Samples\Common\bin\Debug目录下
修改plugins.cfg:
# Defines plugins to load

# Define plugin folder
PluginFolder=./

# Define D3D rendering implementation plugin
Plugin=RenderSystem_Direct3D9_d.dll
Plugin=Plugin_ParticleFX_d.dll
Plugin=Plugin_BSPSceneManager_d.dll
Plugin=Plugin_CgProgramManager_d.dll
Plugin=Plugin_CgProgramManager_d.dll

修改resources.cfg

# Resource locations to be added to the 'boostrap' path
# This also contains the minimum you need to use the Ogre example framework
[Bootstrap]
Zip=../../../Media/packs/OgreCore.zip

# Resource locations to be added to the default path
[General]
FileSystem=../../../Media
FileSystem=../../../Media/fonts
FileSystem=../../../Media/materials/programs
FileSystem=../../../Media/materials/scripts
FileSystem=../../../Media/materials/textures
FileSystem=../../../Media/models
FileSystem=../../../Media/overlays
FileSystem=../../../Media/particle
FileSystem=../../../Media/gui
FileSystem=../../../Media/DeferredShadingMedia
Zip=../../../Media/packs/cubemap.zip
Zip=../../../Media/packs/cubemapsJS.zip
Zip=../../../Media/packs/dragon.zip
Zip=../../../Media/packs/fresneldemo.zip
Zip=../../../Media/packs/ogretestmap.zip
Zip=../../../Media/packs/skybox.zip

终于可以成功完成, 看见demo了。

 

posted @ 2007-07-27 18:06 vcommon 阅读(3099) | 评论 (3)编辑 收藏

矢量字体相当美观和便于移植
         根据microsoft的samples glyph.exe,我们可以很容易的自己去画矢量图形。
         根据microsoft ttf的spec,我们可以创建自己的矢量字体。
         微软为了使小字体清晰,是做了相当大的工作的,包括小字体即使矢量字体也内嵌大量位图。
         具体说来,ttf spec定义了字体的间距等,我们可以根据间距定位从某一点开始,然后利用画线或者画多边形的API,将矢量字体画出来。GetGlyphOutline,但不幸的是它和HDC是相关的。
         linux freetype用来显示字体,反走样后的小字对简单的字符会好看些,但对中文矢量字体就会边缘灰度过多而模糊发虚。而且hinting是有专利费的,而且对汉字而言,对每个字都微调太过耗时,所以linux下的字体比较难看。
         所以对于单片机或其他处理能力不强的嵌入式,都会选择使用点阵字体。
         相比来说,如果点阵字体对大屏幕略显难看,可以配台PC通过矢量字体实时生成点阵。

         无论Photoshop,coreldraw还是其他软件,字体都是特例,编辑的时候就成了位图似的表示。
         而大部分程序,包括UI的,3D游戏的,都会先将字体转变成为一个位图,再显示出来。
         linux的xft就是用来光栅化和渲染用的,可以起到相当大的美化效果。
        
         在了解了一般矢量画法之后(见openVG的流程),下边讲诉freetype的字体绘制过程。

FT_Init_FreeType   FT_New_Face   FT_Set_Char_Size   FT_Set_Transform
FT_Load_Glyph   FT_Get_Glyph   FT_Render_Glyph   FT_Glyph_To_Bitmap
FT_Done_Face   FT_Done_FreeType
FT_Render_Glyph的作用就是遍历所有的点,使用合适的render画上去。
在<freetype/config/ftmodule.h>里有很多render在使用
.......
FT_USE_MODULE(ft_raster1_renderer_class)//黑白色的位图
.......
ft_raster1_render,ft_standard_raster,ft_black_render,Render_Glyph,Render_Single_Pass,Convert_Glyph
Decompose_Curve ,Conic_To,Line_To这些函数都会访问全局的TRaster_Instance的ras.
对所有的y形成一个buffer,保存所有X的值。4096
1:对一条scanline,x1 x2 x3 x4,所以,x1,x2之间是span的,x3,x4之间是span的
2:垂直或斜的不改变方向的成为profile,或叫边,所以一个字是由多个边组成。
3:最后形成这样一个内存结构,边id,边的信息,



 

posted @ 2007-06-21 00:15 vcommon 阅读(3039) | 评论 (0)编辑 收藏

1:OpenVG介绍
   矢量图形具有许多优势,比如无失真,方便生成。然而确很难融合到一般的程序中使用。下边将介绍OpenVG及如何导入,表示和利用现有的矢量图形。
2:OpenVG的PipeLine:
   如果了解OpenGL的话,都知道OpenGL有一个处理管道,我们将所有的数据--顶点,法线,色彩等送到管道的一端进行处理,然后对管道设置旋转,光照,截取等的参数,最后我们就可以得到光栅化,可以显示的图像了。
   OpenVG同样有一个处理管道,他的所有数据是指一个矢量图形的所有点形成的路径,使用的笔触(毛笔的,直线的或虚线的),使用的颜色等绘制参数之类(纯色填充,渐变填充)。 第1步:将以上数据准备好。第二步:如果是带笔触的路径,将生成一个新路径,用于以后的处理,将旧路径设置为不可用。第三步:平移,旋转等变换。第四步:光栅化,将有一个过滤处理,去除一些东西(比如根据屏幕的大小等来调整那些点为可见)。第五步: 剪切和蒙版,将根据设置剪掉一些区域,使用蒙版调整Alpha值等。第六步:根据以上生成的数据,和绘制参数,进行绘制,如颜色填充,渐变等。第七步:图像插值。第八步:blending和反走样。
   那么对于我们使用矢量图形而言,最重要的就是path和path的填充参数了。
3:程序中生成一个path。
   vgSetParameteri
   vgSetParameterfv
   vgAppendPathData
 附图为demo程序截图。
首先move到一个点,然后lineto画了四条线. 根据参数的不同,可以画出复杂的矢量图形。


 PS* ps = (PS*)malloc(sizeof(PS));

 int paths = 5;
 int startp = 0;
 int i = 0;
 int elements = sizeof(unsigned char);
 unsigned char* cmd = (unsigned char*)malloc(elements);
 float color[4]; 

 const float point[] =
 {
  100,100,480,100,480,480,100,480,100,200
  
 };
 ps->m_numPaths = paths;
 ps->m_paths = (PathData*)malloc(paths * sizeof(PathData));

 for(i=0;i<paths;i++)
 {
  ps->m_paths[i].m_capStyle = VG_CAP_ROUND;
  ps->m_paths[i].m_joinStyle = VG_JOIN_ROUND;
  ps->m_paths[i].m_fillRule = VG_EVEN_ODD;
  ps->m_paths[i].m_paintMode = VG_FILL_PATH|VG_STROKE_PATH;
  //the rest of stroke attributes
  ps->m_paths[i].m_miterLimit = 20;
  ps->m_paths[i].m_strokeWidth = 20;

  color[0] = 0.4f;
  color[1] = 0.6f;
  color[2] = 0.8f;
  color[3] = 1.0f;

  ps->m_paths[i].m_strokePaint = vgCreatePaint();
  vgSetParameteri(ps->m_paths[i].m_strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
  vgSetParameterfv(ps->m_paths[i].m_strokePaint, VG_PAINT_COLOR, 4, color);

  if( i == 0)
   cmd[0] = VG_MOVE_TO | VG_ABSOLUTE;
  else
   cmd[0] = VG_LINE_TO | VG_ABSOLUTE;

  ps->m_paths[i].m_fillPaint = vgCreatePaint();
  vgSetParameteri(ps->m_paths[i].m_fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
  vgSetParameterfv(ps->m_paths[i].m_fillPaint, VG_PAINT_COLOR, 4, color);

  ps->m_paths[i].m_path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, (unsigned int)VG_PATH_CAPABILITY_ALL);
  vgAppendPathData(ps->m_paths[i].m_path, elements, cmd, point + startp);
  startp +=2;
 }

  4: openGL的实现方式:
        1: 内部表示,矢量图形系统的内部表示无外乎是点和点,以及点之间的连接规则。OpenVG也是如此,内置VG_MOVE_TO ,VG_LINE_TO,VG_CUBIC_TO等15种连接方式。
        2:光栅化,算法如下:对所有的扫描线y1,y2,y3.....计算,如y1:在y1周围0.5个象素内,计算所有边和y1的交点,因为是0.5象素的距离,所以一个边会有两个交点,minx,maxx.对所有边的minx排序,根据定义的方式是相邻的两个minx,maxx有coverage还是最小和最大的minx和maxx之间有coverage,然后根据panit画点。
               OpenVG的光栅化实现了对一行扫描线的即时扫描,相当底层,可以兼容很多老式或低级设备。所以速度也很慢,需要显示卡或其他的加速才可以更好的支持某些设备。
  5:优缺点:
   OpenVG定义的方式已经非常接近常用的矢量绘图软件了。
   OpenVG其实是定义了一种硬件的实现,利用光栅化的操作,软件实现是很慢的,硬件实现会快的多。
 6:展望:
   OpenVG是为了在手持等跨平台设备中寻求统一,矢量绘图的功能方面其实较弱。
   SVG作为一个显示标准,是方便在网页或其他软件中寻求统一,并易于编辑,丰富视觉感受,无法任意改动应用在程序处理中。

   
以下是一个复杂得矢量图形,在没有优化处理得情况下,耗时50秒才处理显示出来。

posted @ 2007-06-20 12:01 vcommon 阅读(10947) | 评论 (4)编辑 收藏

     摘要:   分析 00 00 00 01 67 42 00 1E 99 A0 B1 31 00 00 00 01 H264的数据流分为两种,一种是NAL UNIT stream(RTP),一种是 bits stream, 两者可以互相转换。我们分析的这个是 bit stream,根据Annex B 00 00 00 01 67 42 00 1E 99 A0 B1 31 是 一个NAL,...  阅读全文

posted @ 2007-05-31 09:42 vcommon 阅读(13356) | 评论 (11)编辑 收藏

仅列出标题
共4页: 1 2 3 4