C++BuilderのTIP集です。

まだ、書き出しですが、徐々に増やしてゆく予定です。
 

目次
  
 

STL ビギナー・ノート

STL マスター・ノート

STL プロフェッサー・ノート

STL フレーム目次付き

STL HTML HELP のダウンロード
 

階層化した(親なし)ディレクトリを作成する関数
 
 ショートパスを返す関数

相対パスを取得する関数

 整数を1024単位のキロ、メガ、ギガ、テラ表記へ変換する関数

2メモリ域を高速スワップさせる関数

デスクトップのクライアント領域を取得する関数

ShellExecuteのデフォルトコマンドを実行する関数

ファイルから日付情報を取得する関数

ファイルへ日付情報を設定する関数

FILETIME を TDateTime() に変更する関数

OutputDebugString

このページで公開されているチップは、すべてテスト済みです。
著作権は、放棄します。 自由にご使用いただいて結構です。


■階層化したディレクトリを作成する関数
  //ネストされたディレクトリを作成する
bool __fastcall CreateNestedDir(AnsiString ADir)
{
  if(!DirectoryExists(ADir)) {
    if(!CreateDir(ADir)) { //作成できない場合は、親を先に作る
      if(!CreateNestedDir(ExtractFileDir(ADir))) return false;
      return CreateDir(ADir);
    }
    return true;
  }
  return true;
}

■ショートパスを返す関数
  //ショートパスを返す関数
AnsiString __fastcall ShortPathFileName(AnsiString fileName)
{
  char *shortPath=(char*)alloca(fileName.Length()+1);
  GetShortPathName(fileName.c_str(),shortPath,fileName.Length()+1);
  return AnsiString(shortPath);
}

■相対パスを取得する関数
  //相対パスを取得する関数

AnsiString __fastcall RelativeFilePath(constAnsiString fileName,constAnsiString baseDir)
{
  // SJIS漢字コード第2バイト目にパスキャラクタ'\'文字が含まれる場合があるため、
  // 一時 WideString 型(UNICODE) に戻す。
  WideString full_fileName =static_cast<WideString>(ExpandFileName(fileName));
  WideString full_baseDir = static_cast<WideString>(ExpandFileName(baseDir));

  if(ExtractFilePath(full_baseDir)!=full_baseDir)
    full_baseDir +='\\';

  int i=1;
  for(i=1;i<=full_fileName.Length();i++)
    if(towupper(full_fileName[i])!=towupper(full_baseDir[i]))
      break;

  if(i==full_fileName.Length()+1)  i = max(i-1,1);

    do {
      if(full_fileName[i]=='\\')break;
      if(i==1)break; i--;
    }while(towupper(full_fileName[i])==towupper(full_baseDir[i]));

  if(i==1)return full_fileName ; //全く一致しない

  WideString relativePath
   = full_fileName.SubString(i+1,full_fileName.Length()-i);

  int relCount =0;

  //一致しない部分のパス区切り総計を求める
  for(int j=i+1; j<= full_baseDir.Length(); j++) {
    if(full_baseDir[j]=='\\') relCount++ ;
  }

  for(int j=0 ; j<relCount ; j++) {
    relativePath = "..\\"+ relativePath;
  }

  return static_cast<AnsiString>(relativePath);
}


■整数を1024単位のキロ、メガ、ギガ、テラ表記へ変換する関数
  //整数を1024単位のキロ、メガ、ギガ、テラ表記へ変換する
AnsiString __fastcall IntToKMGT(__int64 val)
{
  double bytes = double(val);
  int unitno = -1;
  while(bytes>1024){
    bytes/=1024; unitno++;
  }
  AnsiString text;
  if(unitno<0)
    text = IntToStr(val);
  else
    text = FloatToStrF(bytes,ffFixed,5,2);
  if(unitno>=0){
    switch(unitno){
      case 0: text+='K'; break;
      case 1: text+='M'; break;
      case 2: text+='G'; break;
      case 3: text+='T'; break;
      default:text+='?'; break;//テラの次は何?
    }
  }
  return text;
}

■2メモリ域を高速スワップさせる(入れ替える)関数
  //2メモリ域をスワップする
void__fastcall SwapMemory(void*lp1,void*lp2,DWORD size)
{
  //スワップする必要がない
  if( lp1==lp2 || NULL==lp1 || NULL==lp2 || 0==size )return;

  DWORD remSize = size&3 ; //4で割った余り

  if(size>=4) {
     asm{ //クロック数短縮のためアセンブラを使う
       //BCBでアセンブラを組む場合は、汎用レジスタのpush/popの必要はありません。
        mov ecx,size
        shr ecx,2
       mov edi,lp1
        mov esi,lp2
      //アセンブラにラベルをBCBで使用する場合、グローバルに展開されるので、
     //↓重ならない名前をいちいち使用しなければなりません。
      SwapMemory_LOOP:
        mov eax,[edi+ecx*4-4]
        mov ebx,[esi+ecx*4-4]
        mov [esi+ecx*4-4],eax
        mov [edi+ecx*4-4],ebx
        dec ecx
        jnz SwapMemory_LOOP
      }
  }

  if(remSize>0) { //残り3バイト以内のバイト数を複写する
    int loc=(size&~3) ; //←最後の4バイトアラインのオフセット位置
    for(DWORD i=0;i<remSize;i++) {
      BYTE v =((BYTE*)lp1)[loc+i] ;
      ((BYTE*)lp1)[loc+i] = ((BYTE*)lp2)[loc+i] ;
      ((BYTE*)lp2)[loc+i] = v ;
    }
  }

}
 


■デスクトップのクライアント領域を取得する関数
下図の緑線部分の領域(デスクトップクライアント)を取得する

  //デスクトップのクライアント領域を取得する
TRect __fastcall GetDesktopClient()
{
    RECT rect;

    ZeroMemory(&rect,sizeof(rect));
    SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);

    return TRect(rect);
}


■ShellExecuteのデフォルトコマンドを実行する関数
ファイルをダブルクリックした時の動作をシミュレートさせます。

APIのShellExecute()関数のlpszOpパラメータにNULLを渡した場合、実行されるのはデフォルトに指定されているコマンドではなく、"open"(開く)コマンドであるため、ファイルをダブルクリックした時の動作を的確に処理させるためには、ShellExecuteEx()関数を変わりに使用する必要があります。

  //ShellExecuteのデフォルトコマンドを実行する
bool __fastcall ShellExecuteDefault(AnsiString FileName,HWND Handle)
{
    SHELLEXECUTEINFO info;
    ZeroMemory(&info,sizeof(info));
    info.cbSize =sizeof(SHELLEXECUTEINFO) ;
    info.fMask =0 ;
    info.hwnd = Handle ;
    info.lpVerb ="";
    info.lpFile = FileName.c_str();
    info.lpParameters ="";
    info.lpDirectory ="";
    info.nShow = SW_SHOWNORMAL ;
    info.hInstApp =0;
    info.lpIDList = NULL ;
    info.lpClass = NULL ;
    info.hkeyClass =0;
    info.dwHotKey =0;
    info.hIcon =0;
    return ShellExecuteEx(&info) ? true :false;
}

<例>

//ホームページを表示する
ShellExecuteDefault("http://bronze.zero.jp/menisys/",Application->Handle);

■ファイルから日付情報を取得する関数
  //ファイルから日付情報を取得する
bool __fastcall GetFileNameTime(AnsiString FileName,
  FILETIME *lpftCreation, FILETIME *lpftLastAccess,FILETIME *lpftLastWrite)
{
  HANDLE hFile =
    CreateFile(
      FileName.c_str(),
      GENERIC_READ,
      FILE_SHARE_READ,
      NULL, OPEN_EXISTING, 0,0);
  if(!hFile)return false;
  BOOL RESULT = GetFileTime(hFile,lpftCreation,lpftLastAccess,lpftLastWrite);
  CloseHandle(hFile);
  return RESULT?true:false;
}

■ファイルへ日付情報を設定する関数
  //ファイルへ日付情報を設定する
bool __fastcall SetFileNameTime(AnsiString FileName,
  FILETIME *lpftCreation, FILETIME *lpftLastAccess,FILETIME *lpftLastWrite)
{
  HANDLE hFile =
    CreateFile(
      FileName.c_str(),
      GENERIC_READ|GENERIC_WRITE,
      FILE_SHARE_READ|FILE_SHARE_WRITE,
      NULL, OPEN_EXISTING, 0,0);
  if(!hFile)return false;
  BOOL RESULT = SetFileTime(hFile,lpftCreation,lpftLastAccess,lpftLastWrite);
  CloseHandle(hFile);
  return RESULT?true:false;
}

■FILETIME を TDateTime() に変更する関数
  // FILETIME を TDateTime() に変更する
TDateTime FileTimeToDateTime(const FILETIME &FileTime)
{
  SYSTEMTIME SystemTime ;
  ZeroMemory(&SystemTime,sizeof(SYSTEMTIME));
  FileTimeToSystemTime(&FileTime,&SystemTime);
  return TDateTime(SystemTime.wYear,SystemTime.wMonth,SystemTime.wDay)
    + TDateTime(SystemTime.wHour,SystemTime.wMinute,SystemTime.wSecond,SystemTime.wMilliseconds);
}

  まだ、整理していませんが、使ってください。 お役に立てれば幸いです。
 
 

//-----
  //ファイルサイズを得る
long __fastcall GetFileSize(AnsiString FileName)
{
  FILE *st = fopen(FileName.c_str(),"rb");
  long file_size = filelength(_fileno(st));
  fclose(st);
  return file_size;
}
//-----
  //マスクと一致するかどうか求める
bool __fastcall MatchesMaskEx(const AnsiString FileName, const AnsiString Mask)
{
  AnsiString mask1, mask2 ;
  AnsiString fn0, fn1, fn2;
  int i, j, k ;


  i = AnsiPosBackward('.',Mask) ;
  j = Mask.Length();
  if (i > 1) {
    mask1 = Mask.SubString(1, (i - 1));
    if ( j > i )
      mask2 = Mask.SubString((i + 1), (j - i)) ;
    else
      mask2 = '*';
  }else {
    if (i == 0) {
      mask1 = Mask;
      mask2 = '*';
    }else {
      mask1 = '*';
      if ( j > i )
        mask2 = Mask.SubString((i + 1), (j - i)) ;
      else
        mask2 = '*' ;
    }
  }

  fn0 = ExtractFileName(FileName);
  i = AnsiPosBackward('.',fn0) ;
  j = fn0.Length() ;
  if ( i > 1 ) {
    fn1 = fn0.SubString(1, (i - 1));
    if ( j > i )
      fn2 = fn0.SubString((i + 1), (j - i)) ;
    else
      fn2 = "";
  }else {
    if ( i == 0 ) {
      fn1 = fn0;
      fn2 = "";
    }else {
      fn1 = "";
      if ( j > i )
        fn2 = fn0.SubString((i + 1), (j - i)) ;
      else
        fn2 = "" ;
    }
  }

  i = fn1.Length();
  j = mask1.Length();
  k = 1;
  while ((i > 0) && (j > 0)) {
    if (mask1[k] == '*') {
      i = j = 0;
      break;
    }
    if ( mask1[k] == '?' ) {
      if ( StrByteType(fn1.c_str(), (k - 1)) != mbSingleByte )
        i--;
    }else {
      if ( StrByteType(mask1.c_str(), (k - 1)) == mbSingleByte ) {
        if ( toupper(mask1[k]) != toupper(fn1[k]) )
          return false ;
      }else {
        if ( (i <= 1) || (mask1[k] != fn1[k]) ||
             (mask1[k + 1] != fn1[k + 1]) )
          return false ;
        i-- ;
        j-- ;
        k++ ;
      }
    }
    i-- ;
    j-- ;
    k++ ;
  }
  if ( (i > 0) || (j > 0) )
    return false ;

  i = fn2.Length();
  j = mask2.Length();
  k = 1;
  while ( (i > 0) && (j > 0) ) {
    if ( mask2[k] == '*' ) {
      i = j = 0;
      break;
    }
    if ( mask2[k] == '?' ) {
      if ( StrByteType(fn2.c_str(), (k - 1)) != mbSingleByte )
        i--;
    }else {
      if( StrByteType(mask2.c_str(), (k - 1)) == mbSingleByte ) {
        if (toupper(mask2[k]) != toupper(fn2[k]))
          return false ;
      }else {
        if ( (i <= 1) || (mask2[k] != fn2[k]) ||
             (mask2[k + 1] != fn2[k + 1]) )
          return false ;
        i--;
        j--;
        k++;
      }
    }
    i--;
    j--;
    k++;
  }
  if ( (i > 0) || (j > 0) )
    return false ;

  return true ;
}
//-----
  //数値を2進法文字列に変換
AnsiString __fastcall DWORDToBin(DWORD value,int precision)
{
  AnsiString retVal="";
  AnsiString a1="1",a0="0";
  for(int i=0;i<precision;i++) {
    if(value&(1UL<<i)) retVal=a1+retVal;
    else retVal=a0+retVal;
  }
  return retVal;
}
//-----
  //2進法文字列を数値に変換
DWORD __fastcall BinToDWORD(const AnsiString string)
{
  DWORD val=0;
  int length=string.Length();
  char *buff=(char*)alloca(length+1);
  strcpy(buff,string.c_str());
  for(int i=0;i<length;i++) {
    val<<=1;
    if(buff[i]=='1') val|=1;
    else if(buff[i]!='0') {
      throw EConvertError("`"+ string + "' は、2進表記文字列ではありません。");
    }
  }
  return val;
}
//-----
  //AnsiStringをロードする
AnsiString __fastcall LoadAnsiString(AnsiString FileName)
{
  long length = GetFileSize(FileName);
  FILE *fp=fopen(FileName.c_str(),"rb");
  if(!fp) throw EFOpenError("\""+FileName+"\" ←ファイルをオープンできません!");
  AnsiString Result;
  Result.SetLength(length);
  for(int i=0;i<length;i++) {
    Result[i+1] = (char)getc(fp);
  }
  fclose(fp);
  return Result;
}
//-----
  //AnsiStringをセーブする
void __fastcall SaveAnsiString(AnsiString FileName,AnsiString TargetString)
{
  FILE *fp = fopen(FileName.c_str(),"wb");
  if(!fp) throw EFCreateError("\""+FileName+"\" ←ファイルを作成/書込できません!");
  long length = TargetString.Length();
  for(int i=0;i<length;i++) {
    if(putc(TargetString[i+1],fp)==EOF) {
      fclose(fp);
      throw EFCreateError("\""+FileName+"\" ←ファイル作成/書込途中に、書けなくなりました!");
    }
  }
  fclose(fp);
}
//-----
  //Controlを中央に移動
void __fastcall ControlCentering(
  TControl *Dest,TControl *Parent,bool Horizontal,bool Vertical)
{
  int Left,Top,Width,Height;
  if(!Parent) {
    Left=0;
    Top=0;
    Width=Screen->Width;
    Height=Screen->Height;
  }else {
    Left  = Parent->Left   ;
    Top   = Parent->Top    ;
    Width = Parent->Width  ;
    Height= Parent->Height ;
  }
  if(Horizontal)
    Dest->Left = ( Width - Dest->Width )/2 + Left ;
  if(Vertical)
    Dest->Top  = ( Height - Dest->Height )/2 + Top ;
}


//-----

//----------------------------------------------------------
 //SJIS漢字高速判別ヘッダ部(jcype.h)

#ifndef jctypeH
#define jctypeH

extern const bool MNS_iskanji_table[256];
extern const bool MNS_iskanji2_table[256];
#define iskanji(c) ((bool)(MNS_iskanji_table[(unsigned char)(c)]))
#define iskanji2(c) ((bool)(MNS_iskanji2_table[(unsigned char)(c)]))

#endif

//----------------------------------------------------------
 //SJIS漢字高速判別ソース部(jctype.cpp)
const bool MNS_iskanji_table[256]={
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,false,false,false
};

const bool MNS_iskanji2_table[256]={
  false,false,false,false,false,false,false,false, //0x00
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false, //0x10
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false, //0x20
  false,false,false,false,false,false,false,false,
  false,false,false,false,false,false,false,false, //0x30
  false,false,false,false,false,false,false,false,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,false,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,true ,true ,true ,
  true ,true ,true ,true ,true ,false,false,false
};

//----------------------------------------------------------

//-----

  //文字列を、ファイル名として使用できる形に修正する
AnsiString __fastcall StrToValidFileName(const AnsiString S)
{
  AnsiString Result="";
  bool Kanji=false ;
  for(int i=0;i<S.Length();i++) {
    char c = S[i+1] ;
    if(!Kanji) {
      if(iskanji(c)) {
        Kanji=true ;
      }else if(iscntrl(c) ||
        c=='\\' || c=='/' || c== ':' || c==';' || c==',' || c=='*' || c=='?' ||
        c=='\"' || c=='<' || c== '>' || c=='|' ) {
        c = '_';
      }
    }else Kanji= false ;
    Result += c;
  }
  if(Result.Length()>MAX_PATH) Result=Result.SubString(1,MAX_PATH);
  return Result ;
}
//-----

//---------------------------------------------------

  //パッドデータを読む(ヘッダ部)
  #define PAD_1     JOY_BUTTON32
  #define PAD_2     JOY_BUTTON31
  #define PAD_LEFT  JOY_BUTTON27
  #define PAD_RIGHT JOY_BUTTON28
  #define PAD_UP    JOY_BUTTON29
  #define PAD_DOWN  JOY_BUTTON30
  #define PAD_A     JOY_BUTTON1
  #define PAD_B     JOY_BUTTON2
  #define PAD_C     JOY_BUTTON3
  #define PAD_D     JOY_BUTTON4
  #define PAD_E     JOY_BUTTON5
  #define PAD_F     JOY_BUTTON6
  #define PAD_G     JOY_BUTTON7
  #define PAD_H     JOY_BUTTON8
  #define PAD_I     JOY_BUTTON9
  #define PAD_J     JOY_BUTTON10
  #define PAD_K     JOY_BUTTON11
  #define PAD_L     JOY_BUTTON12
  #define PAD_M     JOY_BUTTON13
  #define PAD_N     JOY_BUTTON14
  #define PAD_O     JOY_BUTTON15
  #define PAD_P     JOY_BUTTON16
  #define PAD_Q     JOY_BUTTON17
  #define PAD_R     JOY_BUTTON18
  #define PAD_S     JOY_BUTTON19
  #define PAD_T     JOY_BUTTON20
  #define PAD_U     JOY_BUTTON21
  #define PAD_V     JOY_BUTTON22
  #define PAD_W     JOY_BUTTON23
  #define PAD_X     JOY_BUTTON24
  #define PAD_Y     JOY_BUTTON25
  #define PAD_Z     JOY_BUTTON26
  #define PAD_PLAYERS       (PAD_1|PAD_2)
  #define PAD_DIRECTIONS    (PAD_LEFT|PAD_RIGHT|PAD_UP|PAD_DOWN)
  #define PAD_BUTTONS       (~(DWORD)(PAD_DIRECTIONS|PAD_PLAYERS))

  typedef struct tagTPadKeyMaps {
    bool Enabled;
    int Left,Right,Up,Down;
    int Buttons[26];
  } TPadKeyMaps ;
  extern TPadKeyMaps PadKeyMaps[2];

DWORD __fastcall PadRead(DWORD player /* PAD_1 or PAD_2 */ );

//---------------------------------------------------
  //パッドデータを読む(ソース部)

  TPadKeyMaps PadKeyMaps[2]={
    {
      true,
      VK_LEFT,VK_RIGHT,VK_UP,VK_DOWN,
      {'Z','X','C','A','S','D','Q','W','E',0
      , 0,0 ,0, 0,0 ,0, 0,0 ,0, 0
      , 0,0 ,0, 0,0 ,0}
    },{
      true,
      VK_NUMPAD4,VK_NUMPAD6,VK_NUMPAD8,VK_NUMPAD2,
      {'N','M',',','H','J','K','Y','U','I',0
      , 0,0 ,0, 0,0 ,0, 0,0 ,0, 0
      , 0,0 ,0, 0,0 ,0}
    }
  };

DWORD __fastcall PadRead(DWORD player)
{
  // JOY_BUTTON1〜26 まで対応。
  // 4方向は、最上位ビットに割付けることとする。

  const WORD keyPressed =(1<<15);

  JOYINFOEX jie;
  jie.dwSize=sizeof(jie);
  jie.dwFlags=JOY_RETURNALL|JOY_RETURNCENTERED|JOY_USEDEADZONE;

  const DWORD playerMask[2]={PAD_1,PAD_2};
  for(int i=0;i<2;i++){
    if(player&playerMask[i]){
      MMRESULT mmr=joyGetPosEx((i?JOYSTICKID2:JOYSTICKID1),&jie);
      if(mmr==JOYERR_NOERROR){
        if((int)jie.dwXpos-32768<-8192)  player |= PAD_LEFT;
        if((int)jie.dwXpos-32768>+8192)  player |= PAD_RIGHT;
        if((int)jie.dwYpos-32768<-8192)  player |= PAD_UP;
        if((int)jie.dwYpos-32768>+8192)  player |= PAD_DOWN;
        player|=jie.dwButtons&PAD_BUTTONS;
      }
      if(PadKeyMaps[i].Enabled){
        if(GetKeyState(PadKeyMaps[i].Left)&keyPressed)  player |= PAD_LEFT  ;
        if(GetKeyState(PadKeyMaps[i].Right)&keyPressed) player |= PAD_RIGHT ;
        if(GetKeyState(PadKeyMaps[i].Up)&keyPressed)    player |= PAD_UP    ;
        if(GetKeyState(PadKeyMaps[i].Down)&keyPressed)  player |= PAD_DOWN  ;
        for(int j=0;j<26;j++){
          int key = PadKeyMaps[i].Buttons[j];
          if( key != 0 ){
           if(GetKeyState(key)&(1<<15)){
              player |= 1<<j ;
           }
          }
        }
      }
    }
  }

  return player;
}
//---------------------------------------------------