www.pudn.com > 3D_OnlineGame_Humen.rar > misc.cpp


/* 
*  Copyright (C) 1998 Microsoft Corporation. All Rights Reserved. 
* 
*  File: misc.c 
* 
*  Miscellaneous functions not involving DD and D3D.  Part of D3DApp. 
* 
*  D3DApp is a collection of helper functions for Direct3D applications. 
*  D3DApp consists of the following files: 
*      d3dapp.h    Main D3DApp header to be included by application 
*      d3dappi.h   Internal header 
*      d3dapp.c    D3DApp functions seen by application. 
*      ddcalls.c   All calls to DirectDraw objects except textures 
*      d3dcalls.c  All calls to Direct3D objects except textures 
*      texture.c   Texture loading and managing texture list 
*      misc.c      Miscellaneous calls 
*/ 
#include "stdafx.h" 
#include "XMudClient.h" 
#include "d3dappi.h" 
#include  
#include "MyDInput.h" 
#include "MenuCreateNew.h" 
 
/***************************************************************************/ 
/*                          Setting Defaults                               */ 
/***************************************************************************/ 
/* 
* D3DAppISetDefaults 
* Set all the global variables to their default values.  Do not reset the 
* image files. 
*/ 
void 
D3DAppISetDefaults(void) 
{ 
  int n; 
  char backup[D3DAPP_MAXTEXTURES][50]; 
   
  n = d3dappi.NumTextures; 
  memcpy(&backup[0][0], &d3dappi.ImageFile[0][0], 50 * D3DAPP_MAXTEXTURES); 
  ZEROMEM(d3dappi); 
  memcpy(&d3dappi.ImageFile[0][0], &backup[0][0], 50 * D3DAPP_MAXTEXTURES); 
  d3dappi.NumTextures = n; 
  d3dappi.bAppActive = TRUE; 
  ZEROMEM(d3dapprs); 
  d3dapprs.bZBufferOn = TRUE; 
  d3dapprs.bPerspCorrect = TRUE; //FALSE; 
  d3dapprs.ShadeMode = D3DSHADE_FLAT; //D3DSHADE_GOURAUD; 
  d3dapprs.TextureFilter = D3DFILTER_NEAREST; 
  d3dapprs.TextureBlend = D3DTBLEND_MODULATE; 
  d3dapprs.FillMode = D3DFILL_SOLID; 
  d3dapprs.bDithering = FALSE; 
  d3dapprs.bSpecular = TRUE; 
  d3dapprs.bAntialiasing = FALSE; 
  d3dapprs.bFogEnabled = FALSE; 
  d3dapprs.FogColor = RGB_MAKE(255, 255, 255); 
  d3dapprs.FogMode = D3DFOG_LINEAR; 
  d3dapprs.FogStart = D3DVAL(6.0); 
  d3dapprs.FogEnd = D3DVAL(11.0); 
   
  lpClipper = NULL; 
  lpPalette = NULL; 
  bPrimaryPalettized = FALSE; 
  bPaletteActivate = FALSE; 
  bIgnoreWM_SIZE = FALSE; 
  ZEROMEM(ppe); 
  ZEROMEM(Originalppe); 
  LastError = DD_OK; 
  ZEROMEM(LastErrorString); 
  D3DDeviceDestroyCallback = NULL; 
  D3DDeviceDestroyCallbackContext = NULL; 
  D3DDeviceCreateCallback = NULL; 
  D3DDeviceCreateCallbackContext = NULL; 
} 
 
BOOL D3DAppICallDeviceDestroyCallback(void) 
{ 
  if (D3DDeviceDestroyCallback) { 
    if (CallbackRefCount) { 
      --CallbackRefCount; 
      return (D3DDeviceDestroyCallback)(D3DDeviceDestroyCallbackContext); 
    } 
  } 
  return TRUE; 
} 
 
BOOL D3DAppICallDeviceCreateCallback(int w, int h) 
{ 
  if (D3DDeviceCreateCallback)  
  { 
    ++CallbackRefCount; 
    return (D3DDeviceCreateCallback)(w,h,&d3dappi.lpD3DViewport,D3DDeviceCreateCallbackContext); 
  } 
  return TRUE; 
} 
 
/***************************************************************************/ 
/*            Choosing and verifying the driver and display mode           */ 
/***************************************************************************/ 
/* 
* D3DAppIPickDriver 
* Choose a driver from the list of available drivers which can render to one 
* of the given depths.  Hardware is prefered.  Mono-lighting drivers are 
* prefered over RGB. 
*/ 
BOOL 
D3DAppIPickDriver(int* driver, DWORD depths) 
{ 
  int i, j; 
  j = 0; 
  for (i = 0; i < d3dappi.NumDrivers; i++) 
  { 
    if (d3dappi.Driver[i].Desc.dwDeviceRenderBitDepth & depths) break; 
  } 
  if (i >= d3dappi.NumDrivers)  
  { 
    *driver = D3DAPP_BOGUS; 
    return TRUE; 
  } 
  j = i; 
  for (i = 0; i < d3dappi.NumDrivers; i++)  
  { 
    if (d3dappi.Driver[i].Desc.dwDeviceRenderBitDepth & depths)  
    { 
      if (d3dappi.Driver[i].bIsHardware && !d3dappi.Driver[j].bIsHardware) 
      { 
        j = i; 
      } 
      else if (d3dappi.Driver[i].bIsHardware == d3dappi.Driver[j].bIsHardware)  
      { 
        if (d3dappi.Driver[i].Desc.dcmColorModel & D3DCOLOR_MONO && 
          !(d3dappi.Driver[j].Desc.dcmColorModel & D3DCOLOR_MONO)) 
        { 
          j = i; 
        } 
      } 
    } 
  } 
  if (j >= d3dappi.NumDrivers) *driver = D3DAPP_BOGUS; 
  else                         *driver = j; 
  return TRUE; 
} 
 
BOOL D3DAppIFilterDisplayModes(int driver) 
{ 
  int i; 
  DWORD depths = d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth; 
   
  for (i = 0; i < d3dappi.NumModes; i++)  
  { 
    d3dappi.Mode[i].bThisDriverCanDo = FALSE; 
    if (!(D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp) & depths)) continue; 
    d3dappi.Mode[i].bThisDriverCanDo = TRUE; 
     
  } 
  d3dappi.ThisMode.bThisDriverCanDo = d3dappi.Mode[d3dappi.CurrMode].bThisDriverCanDo; 
  return TRUE; 
} 
 
BOOL D3DAppIPickDisplayMode(int *mode, DWORD depths) 
{ 
  int i, j; 
  for (i = 0; i < d3dappi.NumModes; i++) 
  { 
    if (D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp) & depths) break; 
  } 
  j = i; 
  for (; i < d3dappi.NumModes; i++)  
  { 
    if (!(D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp) & depths)) continue; 
    if (d3dappi.Mode[i].w == DEFULTWND_WIDTH && d3dappi.Mode[i].h == DEFULTWND_HEIGHT && 
      d3dappi.Mode[i].bpp == 16)  
    { 
      j = i; 
      break; 
    } 
  } 
  if (j >= d3dappi.NumModes) *mode = D3DAPP_BOGUS; 
  else                       *mode = j; 
  return TRUE; 
} 
 
/* 
* D3DAppIVerifyDriverAndMode 
* Verifies the selected driver and mode combination.  If the driver is 
* specified, the mode will be changed to accomodate the driver if it's not 
* compatible.  If the driver is not specified, one will be selected which is 
* compatible with the specified mode.  If neither are specified, a suitable 
* pair will be returned. 
*/ 
BOOL 
D3DAppIVerifyDriverAndMode(int* lpdriver, int* lpmode) 
{ 
  DWORD depths; 
  int driver, mode, i; 
  driver = *lpdriver; mode = *lpmode; 
   
  if (mode == D3DAPP_USEWINDOW && !d3dappi.bIsPrimary)  
  { 
    D3DAppISetErrorString("Cannot render to a window when the DirectDraw device is not the primary.\n"); 
    goto exit_with_error; 
  } 
   
  /* 
  * If I've been ask to choose a driver, choose one which is compatible 
  * with the specified mode. 
  */ 
  if (driver == D3DAPP_YOUDECIDE)  
  { 
    if (mode == D3DAPP_USEWINDOW)  
    { 
    /* 
    * I must find a driver for this display depth 
      */ 
      depths = D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp); 
      ATTEMPT(D3DAppIPickDriver(&driver, depths)); 
      if (driver == D3DAPP_BOGUS)  
      { 
        D3DAppISetErrorString("Cannot find a D3D device driver which is compatible with the current display depth.\n"); 
        goto exit_with_error; 
      } 
      /* 
      * I don't need to go through the mode selection since I've 
      * verified it here 
      */ 
      goto ret_ok; 
    }  
    else if (mode == D3DAPP_YOUDECIDE)  
    { 
    /* 
    * I'm free to choose any driver which can use even one 
    * supported depth 
      */ 
      if (d3dappi.bIsPrimary) 
        depths = D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp); 
      else 
        depths = 0; 
      for (i = 0; i < d3dappi.NumModes; i++) 
        depths |= D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp); 
      ATTEMPT(D3DAppIPickDriver(&driver, depths)); 
      if (driver == D3DAPP_BOGUS)  
      { 
        D3DAppISetErrorString("Cannot find a D3D device driver which is compatible with the current display depth or any supported fullscreen mode.\n"); 
        goto exit_with_error; 
      } 
      /* 
      * The mode will be chosen in the next section 
      */ 
    }  
    else  
    { 
    /* 
    * Must pick a driver which uses the given mode depth 
      */ 
      ATTEMPT(D3DAppIPickDriver(&driver, 
        D3DAppIBPPToDDBD(d3dappi.Mode[mode].bpp))); 
      if (driver == D3DAPP_BOGUS)  
      { 
        D3DAppISetErrorString("Cannot find a D3D device driver which is compatible with the specified fullscreen mode.\n"); 
        goto exit_with_error; 
      } 
      /* 
      * I don't need to go through the mode selection since I've 
      * verified it here 
      */ 
      goto ret_ok; 
    } 
  } 
   
  /* 
  * At this stage, I have a driver I want to match the mode to. 
  */ 
  if (mode == D3DAPP_YOUDECIDE)  
  { 
  /* 
  * If it's my choice, I prefer windowed over fullscreen 
    */ 
    if (d3dappi.bIsPrimary)  
    { 
      if (D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp) & 
        d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth)  
      { 
        mode = D3DAPP_USEWINDOW; 
        goto ret_ok; 
      } 
    } 
    /* 
    * Either this is not a primary DD device or the driver cannot use 
    * the Windows display depth 
    */ 
    ATTEMPT(D3DAppIPickDisplayMode(&mode, 
      d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth)); 
    if (mode == D3DAPP_BOGUS)  
    { 
      D3DAppISetErrorString("The selected D3D device driver is not compatible with the current display depth or any supported fullscreen modes.\n"); 
      goto exit_with_error; 
    } 
    goto ret_ok; 
  }  
  else if (mode == D3DAPP_USEWINDOW)  
  { 
  /* 
  * Check to see if this driver can use the Windows display depth 
    */ 
    if (D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp) & 
      d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth)  
    { 
      goto ret_ok; 
    } 
    else  
    { 
    /* 
    * Since it cannot, call this function again to choose any 
    * display mode which is compatible 
      */ 
      mode = D3DAPP_YOUDECIDE; 
      ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode)); 
      if (driver == D3DAPP_BOGUS) 
        goto exit_with_error; 
      goto ret_ok; 
    } 
  }  
  else  
  { 
  /* 
  * Check to see if this driver can use the specified fullscreen mode 
    */ 
    if (D3DAppIBPPToDDBD(d3dappi.Mode[mode].bpp) & 
      d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth)  
    { 
      goto ret_ok; 
    } 
    else  
    { 
    /* 
    * Since it cannot, call this function again to choose any 
    * display mode which is compatible 
      */ 
      mode = D3DAPP_YOUDECIDE; 
      ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode)); 
      if (driver == D3DAPP_BOGUS) 
        goto exit_with_error; 
      goto ret_ok; 
    } 
  } 
   
ret_ok: 
  *lpdriver = driver; *lpmode = mode; 
  return TRUE; 
exit_with_error: 
  return FALSE; 
} 
 
/***************************************************************************/ 
/*                        Dirty Rectangle Functions                        */ 
/***************************************************************************/ 
/* 
* D3DAppIValidateDirtyRects 
* Set the dirty rectangles for the front and back buffers to the entire 
* client size. 
*/ 
void 
D3DAppIValidateDirtyRects(void) 
{ 
  NumDirtyClientRects = 1; NumDirtyBackRects = 1; NumDirtyZRects = 1; 
  SetRect((LPRECT)&DirtyClient[0], 0, 0, d3dappi.szClient.cx, 
    d3dappi.szClient.cy); 
  SetRect((LPRECT)&DirtyBack[0], 0, 0, d3dappi.szClient.cx, 
    d3dappi.szClient.cy); 
  SetRect((LPRECT)&DirtyZ[0], 0, 0, d3dappi.szClient.cx, 
    d3dappi.szClient.cy); 
} 
 
/* 
* D3DAppICopyRectList 
* Copy a list of rectangles to another 
*/ 
void 
D3DAppICopyRectList(int* dstnum, LPD3DRECT dst, int srcnum, LPD3DRECT src) 
{ 
  int i; 
  for (i = 0; i < srcnum; i++) 
    dst[i] = src[i]; 
  *dstnum = srcnum; 
} 
 
/* 
* MERGE macro 
* Set first rectangle to be the smallest rectangle containing both rects 
*/ 
#undef MERGE 
#define MERGE(rc1, rc2)                         \ 
  do {                                        \ 
  if (rc2.x1 < rc1.x1) rc1.x1 = rc2.x1;   \ 
  if (rc2.y1 < rc1.y1) rc1.y1 = rc2.y1;   \ 
  if (rc2.x2 > rc1.x2) rc1.x2 = rc2.x2;   \ 
  if (rc2.y2 > rc1.y2) rc1.y2 = rc2.y2;   \ 
  } while(0) 
 
/* 
* D3DAppIMergeRectLists 
* Merge two lists of rectangles to create another list of rectangles. The 
* merged list of rectangles covers all the area of the original two with NO 
* OVERLAPPING amongst it's rectangles. 
*/ 
void 
D3DAppIMergeRectLists(int* dstnum, LPD3DRECT dst, int src1num, LPD3DRECT src1, 
                      int src2num, LPD3DRECT src2) 
{ 
  LPD3DRECT rc; 
  int* isvalid; 
  int num, i, j, intersect; 
  rc = (LPD3DRECT)malloc(sizeof(D3DRECT) * D3DAPP_MAXCLEARRECTS * 2); 
  memset(rc, 0, sizeof(D3DRECT) * D3DAPP_MAXCLEARRECTS * 2); 
  isvalid = (int*)malloc(sizeof(int) * D3DAPP_MAXCLEARRECTS * 2); 
  memset(isvalid, 0, sizeof(int) * D3DAPP_MAXCLEARRECTS * 2); 
  for (i = 0; i < src1num; i++)  
  { 
    memcpy(&rc[i], &src1[i], sizeof(D3DRECT)); 
    if ((rc[i].x1 == 0 && rc[i].x2 == 0) || 
      (rc[i].y1 == 0 && rc[i].y2 == 0)) 
      isvalid[i] = 0; 
    else if (rc[i].x1 <= rc[i].x2 && rc[i].y1 <= rc[i].y2) 
      isvalid[i] = 1; 
    else 
      isvalid[i] = 0; 
  } 
  for (i = 0; i < src2num; i++)  
  { 
    memcpy(&rc[i + src1num], &src2[i], sizeof(D3DRECT)); 
    if (rc[i + src1num].x1 <= rc[i + src1num].x2 && 
      rc[i + src1num].y1 <= rc[i + src1num].y2) 
      isvalid[i + src1num] = 1; 
    else 
      isvalid[i + src1num] = 0; 
     
  } 
  num = src1num + src2num; 
  for (i = 0; i < num - 1; i++)  
  { 
    if (!isvalid[i]) continue; 
    j = i + 1; 
    do  
    { 
      intersect = 0; 
      for (; j < num; j++)  
      { 
        if (j != i && isvalid[j])  
        { 
          if (rc[i].x1 < rc[j].x1)  
          { 
            if (rc[i].x2 < rc[j].x1) 
              continue; 
          } 
          else  
          { 
            if (rc[j].x2 < rc[i].x1) 
              continue; 
          } 
          if (rc[i].y1 < rc[j].y1)  
          { 
            if (rc[i].y2 < rc[j].y1) 
              continue; 
          } 
          else  
          { 
            if (rc[j].y2 < rc[i].y1) 
              continue; 
          } 
          MERGE(rc[i], rc[j]); 
          isvalid[j] = 0; 
          j = 0; intersect = 1; 
          break; 
        } 
      } 
    } while(intersect); 
  } 
   
  for (i = 0, j = 0; i < num; i++) 
  { 
    if (isvalid[i]) ++j; 
  } 
  if (j > D3DAPP_MAXCLEARRECTS)  
  { 
    for (i = 0; i < num; i++) 
      if (isvalid[i]) break; 
      if (i < num)  
      { 
        *dstnum = 1; 
        dst[0] = rc[i]; 
        for (; i < num; i++)  
        { 
          if (isvalid[i])  
          { 
            MERGE(dst[0], rc[i]); 
          } 
        } 
      }  
      else  
      { 
        *dstnum = 0; 
      } 
  }  
  else  
  { 
    for (i = 0, j = 0; i < num; i++)  
    { 
      if (isvalid[i])  
      { 
        memcpy(&dst[j], &rc[i], sizeof(D3DRECT)); 
        ++j; 
      } 
    } 
    *dstnum = j; 
  } 
  free(rc); 
  free(isvalid); 
} 
 
/***************************************************************************/ 
/*                     Getting and Setting Window Attribs                  */ 
/***************************************************************************/ 
/* 
* D3DAppISetClientSize 
* Set the client size of the given window.  A WM_SIZE message is generated, 
* but ignored. 
*/ 
void 
D3DAppISetClientSize(HWND hwnd, int w, int h, BOOL bReturnFromFullscreen) 
{ 
  RECT rc; 
   
  bIgnoreWM_SIZE = TRUE; 
  if (bReturnFromFullscreen)  
  { 
    SetRect(&rc, 0, 0, w, h); 
    AdjustWindowRectEx(&rc, GetWindowLong(hwnd, GWL_STYLE), 
      GetMenu(hwnd) != NULL, 
      GetWindowLong(hwnd, GWL_EXSTYLE)); 
    SetWindowPos(hwnd, NULL, 0, 0, rc.right-rc.left, 
      rc.bottom-rc.top, 
      SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 
    SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, 
      SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); 
     
  } 
  else  
  { 
  /* 
  * This is the only way to set the client size correctly if the menu 
  * is stacked, so do it unless we are returning from a fullscreen 
  * mode. 
    */ 
    SendMessage(hwnd, WM_SIZE, SIZE_RESTORED, (w + h) << 16); 
    GetWindowRect(hwnd, &rc); 
    SetWindowPos(hwnd, NULL, 0, 0, rc.right-rc.left, 
      rc.bottom-rc.top, 
      SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); 
    SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, 
      SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); 
  } 
  bIgnoreWM_SIZE = FALSE; 
  d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0; 
  ClientToScreen(hwnd, &d3dappi.pClientOnPrimary); 
  d3dappi.szClient.cx = w; d3dappi.szClient.cy = h; 
} 
 
void D3DAppIGetClientWin(HWND hwnd) 
{ 
  RECT rc; 
  if (!d3dappi.bFullscreen)  
  { 
    d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0; 
    ClientToScreen(hwnd, &d3dappi.pClientOnPrimary); 
    GetClientRect(hwnd, &rc); 
    d3dappi.szClient.cx = rc.right; 
    d3dappi.szClient.cy = rc.bottom; 
  } 
  else  
  {   
  /* 
  * In the fullscreen case, we must be careful because if the window 
  * frame has been drawn, the client size has shrunk and this can 
  * cause problems, so it's best to report the entire screen. 
  */ 
    d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0; 
    d3dappi.szClient.cx = d3dappi.ThisMode.w; 
    d3dappi.szClient.cy = d3dappi.ThisMode.h; 
  } 
} 
 
 
/***************************************************************************/ 
/*                              Error reporting                            */ 
/***************************************************************************/ 
 
/* 
* D3DAppISetErrorString 
* Set the global variable which records the last error string. 
*/ 
void 
D3DAppISetErrorString( LPSTR fmt, ... ) 
{ 
  char buff[256]; 
  va_list args; 
   
  buff[0] = 0; 
  va_start(args, fmt); 
  wvsprintf(&buff[0], fmt, args); 
  va_end(args); 
   
  lstrcat(buff, "\r\n"); 
  lstrcpy(LastErrorString, buff); 
} 
 
/* dpf 
* Debug printf.  Very useful for fullscreen exclusive mode or when surfaces 
* are in video memory. 
*/ 
void __cdecl 
dpf( LPSTR fmt, ... ) 
{ 
  char buff[256]; 
  va_list args; 
   
  lstrcpy(buff, "D3DApp: "); 
  va_start(args, fmt); 
  wvsprintf(&buff[lstrlen(buff)], fmt, args); 
  va_end(args); 
   
  lstrcat(buff, "\r\n"); 
  OutputDebugString(buff); 
} 
 
void DelayTime(DWORD delay) 
{ 
  DWORD LastTickCount=timeGetTime(); 
  while(timeGetTime()-LastTickCountsx?fx-sx:sx-fx; 
  dy=fy>sy?fy-sy:sy-fy; 
  hpenNew=CreatePen(PS_SOLID,1,c); 
  hpenOld=(HPEN)SelectObject(hDC,hpenNew); 
  if(dx>dy)  
  {  
    for(i=sy;i<=fy;i++) 
    { 
      MoveToEx(hDC,sx,i,NULL); 
      LineTo(hDC,fx+1,i); 
    } 
  } 
  else 
  {  
    for(i=sx;i<=fx;i++) 
    { 
      MoveToEx(hDC,i,sy,NULL); 
      LineTo(hDC,i,fy+1); 
    } 
  } 
  SelectObject(hDC,hpenOld); 
  DeleteObject(hpenNew); 
} 
 
// ************************************************************************************************ 
// 畫立體邊框 
// ************************************************************************************************ 
void DrawCubicBox(long sx,long sy,long dx,long dy,long R,long G,long B) 
{ 
  COLORREF H=RGB(R  ,G  ,B  ); 
  COLORREF M=RGB(R/2,G/2,B/2); 
  COLORREF L=RGB(R/4,G/4,B/4); 
  DrawLINE(sx  ,sy  ,dx  ,sy  ,M); 
  DrawLINE(sx+1,sy+1,dx-1,sy+1,H); 
  DrawLINE(sx+2,sy+2,dx-2,sy+2,L); 
  DrawLINE(dx  ,sy  ,dx  ,dy  ,M); 
  DrawLINE(dx-1,sy+1,dx-1,dy-1,H); 
  DrawLINE(dx-2,sy+2,dx-2,dy-2,L); 
  DrawLINE(sx  ,sy  ,sx  ,dy  ,L); 
  DrawLINE(sx+1,sy+1,sx+1,dy-1,H); 
  DrawLINE(sx+2,sy+2,sx+2,dy-2,M); 
  DrawLINE(sx  ,dy  ,dx  ,dy  ,L); 
  DrawLINE(sx+1,dy-1,dx-1,dy-1,H); 
  DrawLINE(sx+2,dy-2,dx-2,dy-2,M); 
} 
 
// ************************************************************************************************ 
// 秀中文字 
// ************************************************************************************************ 
void ShowChinese(LPRECT lpRect,char *String,DWORD StringLen,COLORREF GForeColor,COLORREF GBackColor) 
{ 
  SetTextColor(hDC,GForeColor); 
  if(GBackColor==RGB(0,0,0)) SetBkMode(hDC,TRANSPARENT); 
  else                       SetBkColor(hDC,GBackColor); 
  StringLen=StringLenlpDD->CreateSurface(&ddsd,&BackupImage[BackNo],NULL); 
      if(ddrval!=DD_OK)  
      { 
        D3DAppISetErrorString("CreateSurface for texture failed (loadtex).\n%s", D3DAppErrorToString(ddrval)); 
        return NULL; 
      } 
      rcSrc.left  =x; 
      rcSrc.top   =y; 
      rcSrc.right =x+DEFULTWND_WIDTH; 
      rcSrc.bottom=y+40; 
      while(TRUE) 
      { 
        hr=BackupImage[BackNo]->BltFast(0,0,d3dapp->lpBackBuffer,&rcSrc,DDBLTFAST_NOCOLORKEY); 
        if(hr==DD_OK) break; 
        if(hr==DDERR_SURFACELOST) if(!RestoreSurfaces()) break; 
        if(hr!=DDERR_WASSTILLDRAWING) break; 
      } 
      if(d3dapp&&!d3dapp->bFullscreen) BackupImage[!BackNo]=BackupImage[BackNo]; 
    } 
    if(szCompStr) 
    { 
      SIZE Size; 
      RECT rcSrc; 
      HRESULT ddrval; 
      char szBuffer[512]; 
      rcSrc.left  =0; 
      rcSrc.top   =0; 
      rcSrc.right =DEFULTWND_WIDTH; 
      rcSrc.bottom=40; 
      while(TRUE) 
      { 
        hr=d3dapp->lpBackBuffer->BltFast(x,y,BackupImage[BackNo],&rcSrc,DDBLTFAST_NOCOLORKEY); 
        if(hr==DD_OK) break; 
        if(hr==DDERR_SURFACELOST) if(!RestoreSurfaces()) break; 
        if(hr!=DDERR_WASSTILLDRAWING) break; 
      } 
      ddrval =d3dapp->lpBackBuffer->GetDC(&hDC); 
      SelectObject(hDC,g_MessagehFont3); 
      DrawLINE(x,y,x+DEFULTWND_WIDTH-1,y+39,RGB(0,64,64)); 
      DrawCubicBox(x,y,x+DEFULTWND_WIDTH-1,y+39,255,255,0); 
      x+=2; 
      y+=2; 
      if(lpHalfFullMode) 
      { 
        strcpy(szBuffer,lpHalfFullMode); 
        GetTextExtentPoint32(hDC,szBuffer,strlen(szBuffer),&Size); 
        DrawCubicBox(x,y,x+Size.cx,y+17,255,255,255); 
        rcSrc.left  =x; 
        rcSrc.top   =y; 
        ShowChinese(&rcSrc,szBuffer,-1,RGB(128,255,128),RGB(0,0,0)); 
        x+=Size.cx; 
      } 
      if(lpIMEDescription) 
      { 
        strcpy(szBuffer,lpIMEDescription); 
        GetTextExtentPoint32(hDC,szBuffer,strlen(szBuffer),&Size); 
        DrawCubicBox(x,y,x+Size.cx,y+17,255,255,255); 
        rcSrc.left  =x; 
        rcSrc.top   =y; 
        ShowChinese(&rcSrc,szBuffer,-1,RGB(128,255,128),RGB(0,0,0)); 
        x+=Size.cx; 
      } 
      if(strlen(szCompStr)) 
      { 
        GetTextExtentPoint32(hDC,szCompStr,dwCursorPos,&Size); 
        rcSrc.left  =x; 
        rcSrc.top   =y; 
        ShowChinese(&rcSrc,szCompStr,-1,RGB(128,255,128),RGB(0,0,0)); 
        x+=Size.cx; 
      } 
      if(JongCursor) 
      { 
        DrawLINE(x,y+17,x+9,y+17,RGB(128,255,255)); 
      } 
      d3dapp->lpBackBuffer->ReleaseDC(hDC); 
    } 
  } 
  else if(BackupImage[BackNo]) 
  { 
    RECT rcSrc; 
    x=CPF.ptCurrentPos.x; 
    y=CPF.ptCurrentPos.y; 
    rcSrc.left  =0; 
    rcSrc.top   =0; 
    rcSrc.right =DEFULTWND_WIDTH; 
    rcSrc.bottom=40; 
    while(TRUE) 
    { 
      hr=d3dapp->lpBackBuffer->BltFast(x,y,BackupImage[BackNo],&rcSrc,DDBLTFAST_NOCOLORKEY); 
      if(hr==DD_OK) break; 
      if(hr==DDERR_SURFACELOST) if(!RestoreSurfaces()) break; 
      if(hr!=DDERR_WASSTILLDRAWING) break; 
    } 
    BackupImage[BackNo]->Release(); 
    BackupImage[BackNo]=NULL; 
    if(d3dapp&&!d3dapp->bFullscreen) BackupImage[!BackNo]=BackupImage[BackNo]; 
  } 
  ThisCursorTick=timeGetTime(); 
  if(ThisCursorTick>LastCursorTick+500) 
  { 
    JongCursor=!JongCursor; 
    LastCursorTick=ThisCursorTick; 
  } 
  return 1; 
} 
 
// ************************************************************************************************ 
// 中文輸入法(畫選字選單部分) 
// ************************************************************************************************ 
LRESULT HandleCandPaint(void) 
{ 
     long  x,y; 
     SIZE  Size; 
     RECT  rcSrc; 
    DWORD  i,j,len; 
    LPSTR  lpstr; 
  LPDWORD  lpdwOffset; 
  HRESULT  ddrval; 
     BYTE  Shift[2]={ 0xF1,0x20 }; 
     BYTE  Right[2]={ 0xE8,0x20 }; 
 
  if(lpCandList) 
  { 
    x=CPF.ptCurrentPos.x+9; 
    y=CPF.ptCurrentPos.y+20; 
    rcSrc.left  =x; 
    rcSrc.top   =y; 
    rcSrc.right =DEFULTWND_WIDTH; 
    rcSrc.bottom=40; 
    ddrval =d3dapp->lpBackBuffer->GetDC(&hDC); 
    SelectObject(hDC,g_MessagehFont3); 
    if(IsCompositionFinish) 
    { 
      SelectObject(hDC,g_MessagehFont4); 
      GetTextExtentPoint32(hDC,(char*)Shift,2,&Size); 
      rcSrc.left  =x; 
      rcSrc.top   =y; 
      ShowChinese(&rcSrc,(char*)Shift,2,RGB(128,255,128),RGB(0,0,0)); 
      x+=Size.cx; 
      SelectObject(hDC,g_MessagehFont3); 
    } 
    if(lpCandList->dwCount) 
    { 
      lpdwOffset =&lpCandList->dwOffset[0]; 
      lpdwOffset+= lpCandList->dwPageStart; 
      for(i=lpCandList->dwPageStart,j=0;(idwCount)&&(idwPageStart+lpCandList->dwPageSize);i++,j++) 
      { 
        lpstr=(LPSTR)lpCandList+*lpdwOffset++; 
        len=strlen(lpstr); 
        GetTextExtentPoint32(hDC,&CandNumber[j*2],2,&Size); 
        rcSrc.left  =x; 
        rcSrc.top   =y; 
        ShowChinese(&rcSrc,&CandNumber[j*2],2,RGB(128,255,128),RGB(0,0,0)); 
        x+=Size.cx; 
        GetTextExtentPoint32(hDC,lpstr,len,&Size); 
        if(i!=lpCandList->dwSelection) 
        { 
          rcSrc.left  =x; 
          rcSrc.top   =y; 
          ShowChinese(&rcSrc,lpstr,len,RGB(128,255,128),RGB(0,0,0)); 
        } 
        else 
        { 
          rcSrc.left  =x; 
          rcSrc.top   =y; 
          ShowChinese(&rcSrc,lpstr,len,RGB(128,255,128),RGB(0,0,0)); 
        } 
        x+=9*(len+1); 
      } 
      if(idwCount) 
      { 
        SelectObject(hDC,g_MessagehFont4); 
        GetTextExtentPoint32(hDC,(char*)Right,2,&Size); 
        rcSrc.left  =x; 
        rcSrc.top   =y; 
        ShowChinese(&rcSrc,(char*)Right,2,RGB(128,255,128),RGB(0,0,0)); 
        x+=Size.cx; 
        SelectObject(hDC,g_MessagehFont3); 
      } 
    } 
    d3dapp->lpBackBuffer->ReleaseDC(hDC); 
  } 
  return 1; 
} 
 
// ****************************************************************************************** 
// 中文輸入法(變換輸入模式部分) 
// ****************************************************************************************** 
extern HIMC hIMC; 
static WORD LayoutNum[2]= 
{  
  MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), 
  MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_TRADITIONAL) 
}; 
 
void ChangeMode(char ToggleLang,char ToggleHalf) 
{ 
  DWORD dwConv; 
  DWORD dwSent; 
  ActivateKeyboardLayout((HKL)LayoutNum[ToggleLang],KLF_ACTIVATE); 
  ImmGetConversionStatus(hIMC,&dwConv,&dwSent); 
  if(ToggleHalf) dwConv&=~IME_CMODE_FULLSHAPE; 
  else           dwConv|= IME_CMODE_FULLSHAPE; 
  ImmSetConversionStatus(hIMC,dwConv,dwSent); 
} 
 
#define DBCSCODE 3 
#define KeyinCodeMask 31 
 
union _Key { WORD i; char c[2]; } k; 
           BOOL   bNextCodeIsDBCS=FALSE; 
           char   KeyinCodeFlag[256]; 
           WORD   KeyinCodeBuffer[KeyinCodeMask+1]; 
           char   KeyinScanBuffer[KeyinCodeMask+1]; 
           long   KeyinCodeHead=0; 
           long   KeyinCodeTail=0; 
 
extern BOOL g_bGetInputMessage; 
void HandleKeyinDown(long nVirtKey,long lKeyData) 
{ 
  if(g_bGetInputMessage) 
  { 
    if(((KeyinCodeHead+1)&KeyinCodeMask)!=KeyinCodeTail && !(KeyinCodeFlag[(nVirtKey&0xFF)]&0x01)) 
    { 
      KeyinCodeFlag[(nVirtKey&0xFF)]=0x01; 
      KeyinCodeBuffer[KeyinCodeHead]=(WORD)(nVirtKey&0xFF); 
      KeyinScanBuffer[KeyinCodeHead]=0x01; 
      KeyinCodeHead++; 
      KeyinCodeHead&=KeyinCodeMask; 
    } 
  } 
} 
 
void HandleKeyinUp(long nVirtKey,long lKeyData) 
{ 
  if(g_bGetInputMessage) 
  { 
    if(((KeyinCodeHead+1)&KeyinCodeMask)!=KeyinCodeTail) 
    { 
      KeyinCodeFlag[(nVirtKey&0xFF)]=0x00; 
      KeyinCodeBuffer[KeyinCodeHead]=(WORD)(nVirtKey&0xFF); 
      KeyinScanBuffer[KeyinCodeHead]=0x02; 
      KeyinCodeHead++; 
      KeyinCodeHead&=KeyinCodeMask; 
    } 
  } 
} 
 
void FeedKeyinCode(long nVirtKey,long lKeyData) 
{ 
  if(g_bGetInputMessage) 
  { 
    if(nVirtKey>=' ') 
    { 
      if(((KeyinCodeHead+1)&KeyinCodeMask)!=KeyinCodeTail) 
      { 
        KeyinCodeBuffer[KeyinCodeHead]=(WORD)(nVirtKey&0xFF); 
        KeyinScanBuffer[KeyinCodeHead]=0x03; 
        KeyinCodeHead++; 
        KeyinCodeHead&=KeyinCodeMask; 
      } 
    } 
    else if(nVirtKey!=VK_BACK) 
    { 
      if(((KeyinCodeHead+1)&KeyinCodeMask)!=KeyinCodeTail) 
      { 
        KeyinCodeBuffer[KeyinCodeHead]=(WORD)(nVirtKey&0xFF); 
        KeyinScanBuffer[KeyinCodeHead]=0x01; 
        KeyinCodeHead++; 
        KeyinCodeHead&=KeyinCodeMask; 
      } 
    } 
  } 
} 
 
char ReadKeyin(WORD *Keyin) 
{ 
  char Press; 
  if(KeyinCodeTail==KeyinCodeHead) return 0; 
  *Keyin=KeyinCodeBuffer[KeyinCodeTail]; 
   Press=KeyinScanBuffer[KeyinCodeTail]; 
  KeyinCodeTail++; 
  KeyinCodeTail&=KeyinCodeMask; 
  return Press; 
} 
 
   RECT  rcSrc; 
   BOOL  JongCursor,InsertFlag,InputRedraw[2]={ FALSE,FALSE }; 
   char *phrase=NULL; 
   long  xorg,slen; 
 	 long  xloc,yloc; 
   long  xpos,ypos,wval,hval; 
  DWORD  LastKeyingTick; 
  DWORD  LastCursorTick; 
//  LPDIRECTDRAWSURFACE InputArea=NULL; 
extern rmfullglobals myglobs; 
extern CMenuCreateNew m_MenuCreateNew; 
 
void CheckBufferPhrase(char *buffer,char *phrase) 
{ 
  DWORD i; 
  for(i=0;i(xloc-xorg)+1;i--) 
        { 
          phrase[i]=phrase[i-2]; 
          buffer[i]=buffer[i-2]; 
        } 
        phrase[xloc  ]=2; // 中文一 
        phrase[xloc+1]=3; // 中文二 
        buffer[xloc++]=k.c[0]; 
        ReadKeyin(&k.i); 
        buffer[xloc++]=k.c[0]; 
        InputRedraw[0]=TRUE; 
        InputRedraw[1]=TRUE; 
      } 
      // 字數檢查 
      else if(xloc-xorg(xloc-xorg);i--) 
        { 
          phrase[i]=phrase[i-1]; 
          buffer[i]=buffer[i-1]; 
        } 
        phrase[xloc  ]=1; // 英文 
        buffer[xloc++]=k.c[0]; 
        InputRedraw[0]=TRUE; 
        InputRedraw[1]=TRUE; 
      } 
      // 字數檢查 
      else if(xloc-xorgLastKeyingTick+500) 
  { 
    k.i=KeyCode; 
  } 
  if(k.i) 
  { 
    switch(k.c[0]) 
    { 
    case VK_BACK:  // BACKSPACE 
      if((xloc-xorg>0&&phrase[xloc-xorg-1]==3)||(xloc-xorg>1&&phrase[xloc-xorg-2]==2)) loops=2; 
      else                                                                             loops=1; 
      for(j=0;j0) 
        { 
          xloc--; 
          for(i=(xloc-xorg);i0;i--) 
      { 
        if(i<0) break; 
        if(phrase[i]==1&&buffer[i]!=0x20) break; 
        if(phrase[i]==3&&buffer[i--]!=0x40&&buffer[i]!=0xA1) break; 
      } 
      xloc=xorg+i+1; 
      InputRedraw[0]=TRUE; 
      InputRedraw[1]=TRUE; 
      break; 
    case VK_INSERT:  //INS 
      InsertFlag=!InsertFlag; 
      break; 
    case VK_DELETE:  //DEL 
      if(xloc-xorg=loops) 
      { 
        for(j=0;j0) 
          { 
            xloc--; 
          } 
        } 
        InputRedraw[0]=TRUE; 
        InputRedraw[1]=TRUE; 
      } 
      break; 
    case VK_RIGHT:  //RIGHT 
      if(phrase[xloc-xorg]==2) loops=2; 
      else                     loops=1; 
      if(xloc-xorglpBackBuffer->GetDC(&hDC); 
    SelectObject(hDC,g_MessagehFont3); 
    rcSrc.left  =xpos; 
    rcSrc.top   =ypos; 
//    PutIMG(xpos-2,ypos-2,InputArea); 
 
//    if(m_MenuCreateNew.bPassword) 
//		ShowChinese(&rcSrc,altime,strlen(Rtrim(buffer)),RGB(255,255,255),RGB(0,0,0)); 
//    else 
		ShowChinese(&rcSrc,buffer,strlen(Rtrim(buffer)),RGB(255,255,255),RGB(0,0,0)); 
    if(JongCursor) 
    { 
      GetTextExtentPoint32(hDC,buffer,xloc,&Size); 
      if(InsertFlag) DrawLINE(xpos+Size.cx,ypos   ,xpos+Size.cx+9,ypos+17,RGB(255,255,255)); 
      else           DrawLINE(xpos+Size.cx,ypos+17,xpos+Size.cx+9,ypos+17,RGB(255,255,255)); 
    } 
    d3dapp->lpBackBuffer->ReleaseDC(hDC); 
  } 
  ThisCursorTick=timeGetTime(); 
  if(ThisCursorTick>LastCursorTick+500) 
  { 
    JongCursor=!JongCursor; 
    LastCursorTick=ThisCursorTick; 
    InputRedraw[0]=TRUE; 
    InputRedraw[1]=TRUE; 
  } 
  HandleCompPaint(); 
  HandleCandPaint(); 
  return Retval; 
} 
 
void InputFinish(void) 
{ 
  ChangeMode(0,TRUE); 
  HandleCompPaint(); 
  HandleCandPaint(); 
  DisableIME(myglobs.hWndMain); 
//  if(InputArea) { Free(InputArea); InputArea=NULL; } 
  if(phrase) { free(phrase); phrase=NULL; } 
} 
 
extern DEVMODE g_DevMode; 
BOOL InitResolution(void) 
{ 
   long       iSel=-1; 
  DWORD       iMode=0; 
  DEVMODE     DevMode; 
  //設定顯示模式 
  g_DevMode.dmSize=sizeof(DEVMODE); 
  EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&g_DevMode); 
  iSel=-1; 
  // 先找解析度和目前一樣的 
  iMode=0; 
  while(TRUE) 
  { 
    DevMode.dmSize=sizeof(DEVMODE); 
    if(!EnumDisplaySettings(NULL,iMode,&DevMode)) break; 
    if(DevMode.dmBitsPerPel==16&&DevMode.dmPelsWidth==g_DevMode.dmPelsWidth&&DevMode.dmPelsHeight==g_DevMode.dmPelsHeight) 
    { 
      iSel=iMode; 
      DevMode.dmFields=DM_BITSPERPEL; 
      DevMode.dmBitsPerPel=16; 
      ChangeDisplaySettingsEx(NULL,&DevMode,NULL,CDS_UPDATEREGISTRY,NULL); 
    } 
    iMode++; 
  } 
  // 找到沒 
  if(iSel<0) 
  { 
    // 再找解析度比預設高的即可但可與目前不同 
    iMode=0; 
    while(TRUE) 
    { 
      DevMode.dmSize=sizeof(DEVMODE); 
      if(!EnumDisplaySettings(NULL,iMode,&DevMode)) break; 
      if(DevMode.dmBitsPerPel==16&&DevMode.dmPelsWidth>=DEFULTWND_WIDTH&&DevMode.dmPelsHeight>=DEFULTWND_HEIGHT) 
      { 
        iSel=iMode; 
        DevMode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; 
        DevMode.dmBitsPerPel=16; 
        ChangeDisplaySettingsEx(NULL,&DevMode,NULL,CDS_UPDATEREGISTRY,NULL); 
        break; 
      } 
      iMode++; 
    } 
    if(iSel<0) 
    { 
      return FALSE; 
    } 
  } 
  return TRUE; 
} 
 
void QuitResolution(void) 
{ 
  g_DevMode.dmSize=sizeof(DEVMODE); 
  g_DevMode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; 
  ChangeDisplaySettingsEx(NULL,&g_DevMode,NULL,CDS_UPDATEREGISTRY,NULL); 
} 
 
void ProcessMessage(void) 
{ 
  MSG Msg; 
 
  if(PeekMessage(&Msg,NULL,0,0,PM_REMOVE)) 
  { 
    if(Msg.message==WM_QUIT) 
    { 
      exit(1); 
    } 
    TranslateMessage(&Msg); 
    DispatchMessage(&Msg); 
  } 
}