WinAPI函数库

{=========================================================================
   功  能: WinAPI函数库
   时  间: SilverLong 2005/10/09
   版  本: 1.0
   备  注:
=========================================================================}
unit WinAPI;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, ExtCtrls, Mask, ImgList, ToolWin ,winsock,
  ComObj,WinInet,Registry, Buttons, Menus,ShellApi, Grids,TlHelp32;

const
        SystemBasicInformation = 0;
        SystemPerformanceInformation = 2;
        SystemTimeInformation = 3;
 
type
        TPDWord = ^DWORD;

        TSystem_Basic_Information = packed record
                dwUnknown1: DWORD;
                uKeMaximumIncrement: ULONG;
                uPageSize: ULONG;
                uMmNumberOfPhysicalPages: ULONG;
                uMmLowestPhysicalPage: ULONG;
                uMmHighestPhysicalPage: ULONG;
                uAllocationGranularity: ULONG;
                pLowestUserAddress: Pointer;
                pMmHighestUserAddress: Pointer;
                uKeActiveProcessors: ULONG;
                bKeNumberProcessors: byte;
                bUnknown2: byte;
                wUnknown3: word;
        end;

type
        TSystem_Performance_Information = packed record
        liIdleTime: LARGE_INTEGER; {LARGE_INTEGER}
        dwSpare: array[0..75] of DWORD;
end;

type
        TSystem_Time_Information = packed record
        liKeBootTime: LARGE_INTEGER;
        liKeSystemTime: LARGE_INTEGER;
        liExpTimeZoneBias: LARGE_INTEGER;
        uCurrentTimeZoneId: ULONG;
        dwReserved: DWORD;
end;

var
        NtQuerySystemInformation: function(infoClass: DWORD;
        buffer: Pointer;
        bufSize: DWORD;
        returnSize: TPDword): DWORD; stdcall = nil;


        liOldIdleTime: LARGE_INTEGER = ();
        liOldSystemTime: LARGE_INTEGER = ();
        SysBaseInfo: TSystem_Basic_Information;
        SysPerfInfo: TSystem_Performance_Information;
        SysTimeInfo: TSystem_Time_Information;
        status: Longint; {long}
        dbSystemTime: Double;
        dbIdleTime: Double;
        //function GetCPUUsage:Double;

const
        {第一组:按钮内容选择}
        OKOnly=0;{仅显示"确定"按钮}
        OKCancel=1;{显示"确定"和"取消"按钮}
        AbortRetryIgnore=2;{"中止""重试""放弃"}
        YesNoCancel=3;{"是""否""取消"}
        YesNo=4;{"是"和"否"}
        RetryCancel=5;{"重试""取消"}
        {第二组:显示图标选择}
        Critical=16;{"STOP"图标}
        Question=32;{"?"图标}
        Excalamation=48;{"!"图标}
        Information=64;{"i"图标}
        {第三组:缺省指针位置(激活状态)}
        DefaultButton1=0;{第一按钮}
        DefaultButton2=256;{第二按钮}
        DefaultButton3=512;{第三按钮}
        {第四组:信息框方式}
        ApplicationModal=0;{应用方式}
        SystemModal=4096;{系统方式}

   //功  能: 将Pascal字符串转换成null结尾字符串函数
   function StrToPch(Str:string):PChar;
   //功  能: 消息框
   function MsgBox(msg:string;mbType:Word;title:string):Word;

   //功  能: 拷贝文件
   function CopyF(var ExistingFileName:string;const NewFileName:string;var
        Mode:Integer):Boolean;
   {************************************}
   //功  能: 得到进程号
   function GetProID(ProName:String):int64;
   //功  能: 杀死进程
   procedure KillProByName(proname:String);
   //功  能: 将字符转换成大写
   function UP(var str:String):String;
   //功  能: 避免调试
   function EnableDebugPrivilege: Boolean;
   //功  能: 杀死进程
   function KillTask(ExeFileName: string): Integer;
   //功  能: 取得一台机器的CPU占用率
   function GetCPUUsage:Double;
   //功  能: 取得用户名称
   function GetUserName: AnsiString;
   //功  能: 取得 Windows 产品序号
   function GetWindowsProductID: string;
   //功  能: 屏蔽系统按键
   Function ShieldSyskeystoke(State:Integer):Boolean;
   //隐藏Windows的任务条
   procedure hideTaskbar(Title:String);
   //功  能: 显示Windows的任务条
   procedure showTaskbar(Title:String);
   //功  能: 驱动器容量
   Procedure ShowDriverContent(Driver:PChar;var AllContent,DoContent:PChar);
   //重定向一个DOS应用程序
   function CreateDOSProcessRedirected(const CommandLine, InputFile,
      OutputFile, ErrMsg :string):boolean;
 
implementation


{=================================================================
  功  能: 将Pascal字符串转换成null结尾字符串函数
  参  数: Str 原字符串
  返回值: PChar
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function StrToPch(Str:string):PChar;
var
        a:PChar;
begin
        a:=StrAlloc(Length(Str)+1);
        StrPCopy(a,Str);
        StrToPch:=a;
end;

{=================================================================
  功  能: 消息框
  参  数: msg 消息
          mbType 按钮类型
          title 标题
  返回值: Word
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function MsgBox(msg:string;mbType:Word;title:string):Word;
var     hWnd1:HWND;
        pText,pCaption:Pchar;
begin
        pText:=StrToPch(title);
        pCaption:=StrToPch(msg);
        hWnd1:=GetActiveWindow();
        MsgBox:=MessageBox(hWnd1,pText,pCaption,mbType);
end;

{=================================================================
  功  能: 拷贝文件
  参  数: ExistingFileName 原文件名(包含路径)
          NewFileName 新的文件名(包含路径)
          Mode 模式
  返回值: false 失败,true 成功
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function CopyF(var ExistingFileName:string;const NewFileName:string;var
        Mode:Integer):Boolean;
var
        EFile,NFile:PChar;
        CpFlag,FailIfExists:Boolean;
        msg:string;
        ErrID,mbType:integer;
begin
        EFile:=StrToPch(ExistingFileName);
        NFile:=StrToPch(NewFileName);
        if (Mode=1) or (Mode=3) then
                FailIfExists:=True
        else
                FailIfExists:=False;
        CpFlag:=CopyFile(EFile,NFile,FailIfExists);
        if not CpFlag then
        begin
                ErrID:=GetLastError();
                ExistingFileName:=SysErrorMessage(ErrID);
                if Mode<2 then
                begin
                        msg:='CopyFile Error!';
                        mbType:=OKOnly+Excalamation;
                        MsgBox(msg,mbType,ExistingFileName);
                end;
                Mode:=ErrID;
        end;
        CopyF:=CpFlag;
end;


{=================================================================
  功  能: 将字符转换成大写
  参  数: str 字符串
  返回值: 转换成大写的字符串
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function UP(var str:String):String;
var j:integer;
begin
  try
    for j := 1 to length(str) do
      str[j] := UpCase(str[j]);
  except
  end;
end;

{=================================================================
  功  能: 避免调试
  参  数: 无
  返回值: false 失败,true 成功
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function EnableDebugPrivilege: Boolean;
  function EnablePrivilege(hToken: Cardinal; PrivName: string; bEnable: Boolean): Boolean;
  var
    TP: TOKEN_PRIVILEGES;
    Dummy: Cardinal;
  begin
    TP.PrivilegeCount := 1;
    LookupPrivilegevalue(nil, pchar(PrivName), TP.Privileges[0].Luid);
    if bEnable then
      TP.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
    else TP.Privileges[0].Attributes := 0;
    AdjustTokenPrivileges(hToken, False, TP, SizeOf(TP), nil, Dummy);
    Result := GetLastError = ERROR_SUCCESS;
  end;

var
  hToken: Cardinal;
begin
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken);

  if EnablePrivilege(hToken, 'SeDebugPrivilege', True) then
        ShowMessage('OK');
       
  CloseHandle(hToken);
end;

{=================================================================
  功  能: 杀死进程
  参  数: ExeFileName:String 程序名
  返回值: Integer 小于0则删除失败,大于0则删除成功
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function KillTask(ExeFileName: string): Integer;
const
  PROCESS_TERMINATE = $0001;
var
  ContinueLoop: BOOL;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
begin
  Result := 0;
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);

  while Integer(ContinueLoop) <> 0 do
  begin
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
      UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
      UpperCase(ExeFileName))) then
      Result := Integer(TerminateProcess(
        OpenProcess(PROCESS_TERMINATE,
        BOOL(0),
        FProcessEntry32.th32ProcessID),
        0));
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
end;


{=================================================================
  功  能: 得到进程号
  参  数: ProName:String 程序名
  返回值: int64 进程号
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function GetProID(ProName:String):int64;
var //p: pProcessInfo;
    ContinueLoop: BOOL;
    FSnapshotHandle: THandle;
    FProcessEntry32: TProcessEntry32;
    tmp:String;
begin
  result:=0;
  try
    Up(ProName);
    FSnapshotHandle := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS,0);
    FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
    ContinueLoop := Process32First(FSnapshotHandle,FProcessEntry32);
    while ContinueLoop do
    begin
      //New(p);
      tmp:=FProcessEntry32.szExeFile;
      Up(tmp);
      if ProName=tmp then
      begin
        result:= FProcessEntry32.th32ProcessID;
        break;
      end;
      ContinueLoop:=Process32Next(FSnapshotHandle,FProcessEntry32);
    end;
  except
  end;
end;

{=================================================================
  功  能: 杀死进程
  参  数: ProName:String 程序名
  返回值: 无
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
procedure KillProByName(proname:String);
var
  HProcess: Thandle;
  uExitCode: int64;
  ID:int64;
begin
  try
    ID := GetProID(proname);
    if ID > 0 then
      hProcess := openprocess(PROCESS_TERMINATE,FALSE,ID);
    if TerminateProcess(hProcess,3838) then
    begin
        Application.MessageBox('删除进程成功.', 'Look', MB_OK);
    end;
  except
  end;
end;

 

function Li2Double(x: LARGE_INTEGER): Double;
begin
        Result := x.HighPart * 4.294967296E9 + x.LowPart
end;

{=================================================================
  功  能: 取得一台机器的CPU占用率
  参  数: 无
  返回值: CPU占用率
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function GetCPUUsage:Double;
var
        bLoopAborted : boolean;
begin
        if @NtQuerySystemInformation = nil then
                NtQuerySystemInformation := GetProcAddress(GetModuleHandle('ntdll.dll'),
                        'NtQuerySystemInformation');

        status := NtQuerySystemInformation(SystemBasicInformation
                , @SysBaseInfo, SizeOf(SysBaseInfo), nil);
        if status <> 0 then Exit;

        bLoopAborted := False;
        while not bLoopAborted do
        begin

                status := NtQuerySystemInformation(SystemTimeInformation
                        , @SysTimeInfo, SizeOf(SysTimeInfo), 0);
                if status <> 0 then Exit;

                status := NtQuerySystemInformation(SystemPerformanceInformation
                        , @SysPerfInfo, SizeOf(SysPerfInfo),
                        nil);
                if status <> 0 then Exit;

                if (liOldIdleTime.QuadPart <> 0) then
                begin

                        dbIdleTime := Li2Double(SysPerfInfo.liIdleTime) - Li2Double(liOldIdleTime);
                        dbSystemTime := Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(liOldSystemTime);

                        dbIdleTime := dbIdleTime / dbSystemTime;

                        dbIdleTime := 100.0 - dbIdleTime * 100.0 / SysBaseInfo.bKeNumberProcessors + 0.5;

                        Result:=dbIdleTime;
                        bLoopAborted:=True;

                end;
        // store new CPU‘s idle and
        End;
End;

{=================================================================
  功  能: 取得用户名称
  参  数: 无
  返回值: 用户名称
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function GetUserName: AnsiString;
var
        lpName: PAnsiChar;
        lpUserName: PAnsiChar;
        lpnLength: DWORD;
begin
        Result := '';
        lpnLength := 0;
        WNetGetUser(nil, nil, lpnLength); // 取得字串所需的长度
        if lpnLength > 0 then
        begin
                GetMem(lpUserName, lpnLength);
                if WNetGetUser(lpName, lpUserName, lpnLength) = NO_ERROR then
                        Result := lpUserName;
                FreeMem(lpUserName, lpnLength);
        end;
end; { GetUserName }


{=================================================================
  功  能: 取得 Windows 产品序号
  参  数: 无
  返回值: Windows 产品序号
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function GetWindowsProductID: string;
var
        reg: TRegistry;
begin
        Result := '';
        reg := TRegistry.Create;
        with reg do
        begin
                RootKey := HKEY_LOCAL_MACHINE;
                OpenKey('Software/Microsoft/Windows/CurrentVersion', False);
                Result := ReadString('ProductID');
        end;
        reg.Free;
End;


{=================================================================
  功  能: 屏蔽系统按键
  参  数: State 状态
  返回值: Boolean(成功:  True  失败:  False)
  备 注:也许你希望程序在运行时不想让用户按系统按键 Alt-Tab
        或 Ctrl-Alt-Del,那么可以通过以下的程序来屏蔽这些按键。
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
Function ShieldSyskeystoke(State:Integer):Boolean;
var tmp,Flag :integer;
Begin
        Result:=False;
        tmp := 0;
        Flag := 1;
        Case State Of
                1:Begin
                        SystemParametersInfo(SPI_SETFASTTASKSWITCH, Flag, @tmp, 0); //屏蔽 Alt-Tab
                        Result:=True;
                  End;
                2:Begin
                        SystemParametersInfo(SPI_SCREENSAVERRUNNING,Flag, @tmp, 0);//屏蔽 Ctrl-Alt-Del
                        Result:=True;
                  End;
        Else
                Result:=False;
        End;
End;

{=================================================================
  功  能: 隐藏Windows的任务条
  参  数: Title 标题条
  返回值: 无
  备 注:找到标题条的句
        柄,然后向它发送相应消息(SW_HIDE)即可
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
procedure hideTaskbar(Title:String);
var     wndHandle : THandle;
        wndClass : array[0..50] of Char;
begin
        StrPCopy(@wndClass[0], Title);//'Shell_TrayWnd');
        wndHandle := FindWindow(@wndClass[0], nil);
        ShowWindow(wndHandle, SW_HIDE);
End;

{=================================================================
  功  能: 显示Windows的任务条
  参  数: Title 标题条
  返回值: 无
  备 注:找到标题条的句
        柄,然后向它发送相应消息(SW_RESTORE)即可
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
procedure showTaskbar(Title:String);
var     wndHandle : THandle;
        wndClass : array[0..50] of Char;
begin
        StrPCopy(@wndClass[0], Title);//'Shell_TrayWnd');
        wndHandle := FindWindow(@wndClass[0], nil);
        ShowWindow(wndHandle, SW_RESTORE);
end;

{=================================================================
  功  能: 驱动器容量
  参  数: Driver 驱动器(要显示的驱动器名,如:driver:='c:/';)
  返回值: String(驱动器容量)
  备 注:要得到驱动器的容量和剩余容量,用下面的程序
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
Procedure ShowDriverContent(Driver:PChar;var AllContent,DoContent:PChar);
var
        sec1, byt1, cl1, cl2:Longword;
        AllStr,DoString:String;
Begin
        GetDiskFreeSpace(Driver, sec1, byt1, cl1, cl2);
        cl1 := cl1 * sec1 * byt1;
        cl2 := cl2 * sec1 * byt1;

        AllStr:=Formatfloat('###,##0',cl2);//'该驱动器总共容量' + Formatfloat('###,##0',cl2) + '字节';
        DoString:=Formatfloat('###,##0',cl1);//'该驱动器可用容量' + Formatfloat('###,##0',cl1) + '字节';
        AllContent:=PChar(AllStr);
        DoContent:=PChar(DoString);        
End;


{=================================================================
  功  能        : 重定向一个DOS应用程序
  描述          : executes a (DOS!) app defined in the CommandLine
                  parameter redirected to take input from InputFile
                  and give output to OutputFile
 返回值         : True on success
 参  数         :
                  CommandLine : the command line for the app,
                                including its full path
                  InputFile   : the ascii file where from the app
                                takes input
                  OutputFile  : the ascii file to which the app's
                                output is redirected
                  ErrMsg      : additional error message string.
                                Can be empty
 Error checking : YES
 Target         :
 版 本          :1.0  2005-10-18 9:05
 备 注          :
 例程           :
      CreateDOSProcessRedirected('C:/MyDOSApp.exe',
                                 'C:/InputPut.txt',
                                 'C:/OutPut.txt',
                                 'Please, record this message')
=================================================================}
function CreateDOSProcessRedirected(const CommandLine, InputFile,
     OutputFile, ErrMsg :string):boolean;
const
  ROUTINE_ID = '[function: CreateDOSProcessRedirected ]';
var
  OldCursor     : TCursor;
  pCommandLine  : array[0..MAX_PATH] of char;
  pInputFile,
  pOutPutFile   : array[0..MAX_PATH] of char;
  StartupInfo   : TStartupInfo;
  ProcessInfo   : TProcessInformation;
  SecAtrrs      : TSecurityAttributes;
  hAppProcess,
  hAppThread,
  hInputFile,
  hOutputFile   : THandle;
begin
  Result := False;
  { Check for InputFile existence }
  if not FileExists(InputFile)
  then
raise Exception.CreateFmt(ROUTINE_ID          + #10 +  #10 +
                              'Input file * %s *' + #10 +
                              'does not exist'    + #10 +  #10 +
                              ErrMsg, [InputFile]);
  { Save the cursor }
  OldCursor     := Screen.Cursor;
  Screen.Cursor := crHourglass;
  { Copy the parameter Pascal strings to null terminated
strings }
  StrPCopy(pCommandLine, CommandLine);
  StrPCopy(pInputFile, InputFile);
  StrPCopy(pOutPutFile, OutputFile);
  TRY
{ Prepare SecAtrrs structure for the CreateFile calls.
      This SecAttrs structure is needed in this case because
      we want the returned handle can be inherited by child
      process. This is true when running under WinNT.
      As for Win95, the documentation is quite ambiguous }
FillChar(SecAtrrs, SizeOf(SecAtrrs), #0);
SecAtrrs.nLength              := SizeOf(SecAtrrs);
SecAtrrs.lpSecurityDescriptor := nil;
SecAtrrs.bInheritHandle       := True;
{ Create the appropriate handle for the input file }

hInputFile := CreateFile(pInputFile,
                        {pointer to name of the file }
                        GENERIC_READ or GENERIC_WRITE,
                        {access (read-write) mode }
                        FILE_SHARE_READ or FILE_SHARE_WRITE,
                        {share mode }
                        @SecAtrrs,
                        {pointer to security attributes }
                        OPEN_ALWAYS,
                        {how to create }
                        FILE_ATTRIBUTE_NORMAL or FILE_FLAG_WRITE_THROUGH,
                        { file attributes }
                        0 ); {handle to file with attributes to copy }
{ Is hInputFile a valid handle? }
if hInputFile = INVALID_HANDLE_VALUE
then
      raise Exception.CreateFmt(ROUTINE_ID + #10 +  #10 +
            'WinApi function CreateFile returned an' +
            'invalid handle value'  + #10 +
            'for the input file * %s *' + #10 + #10 +
            ErrMsg, [InputFile]);
{ Create the appropriate handle for the output file }
hOutputFile := CreateFile(pOutPutFile,
                        {pointer to name of the file }
                        GENERIC_READ or GENERIC_WRITE,
                        {access (read-write) mode }
                        FILE_SHARE_READ or FILE_SHARE_WRITE,
                        {share mode }
                        @SecAtrrs,
                        {pointer to security attributes }
                        CREATE_ALWAYS,
                        { how to create }
                        FILE_ATTRIBUTE_NORMAL or FILE_FLAG_WRITE_THROUGH,
                        {file attributes }
                        0 );
                        {handle to file with attributes to copy }
                       
{ Is hOutputFile a valid handle? }
if hOutputFile = INVALID_HANDLE_VALUE
then
      raise Exception.CreateFmt(ROUTINE_ID + #10 +  #10 +
            'WinApi function CreateFile returned an' +
            'invalid handle value'  + #10 +
            'for the output file * %s *' + #10 + #10 +
            ErrMsg, [OutputFile]);
{ Prepare StartupInfo structure }
FillChar(StartupInfo, SizeOf(StartupInfo), #0);
StartupInfo.cb          := SizeOf(StartupInfo);
StartupInfo.dwFlags     := STARTF_USESHOWWINDOW or
                               STARTF_USESTDHANDLES;
StartupInfo.wShowWindow := SW_HIDE;
StartupInfo.hStdOutput  := hOutputFile;
StartupInfo.hStdInput   := hInputFile;
{ Create the app }
Result := CreateProcess(nil,                          
           { pointer to name of executable module }
        pCommandLine,                 
           { pointer to command line string }
        nil,                          
           { pointer to process security attributes }
        nil,                          
           { pointer to thread security attributes }
        True,                         
           { handle inheritance flag }
        HIGH_PRIORITY_CLASS,          
           { creation flags }
        nil,                          
           { pointer to new environment block }
        nil,                          
           { pointer to current directory name }
        StartupInfo,                  
           { pointer to STARTUPINFO }
        ProcessInfo);                 
           { pointer to PROCESS_INF }
{ wait for the app to finish its job and take the
      handles to free them later }
if Result
then
      begin
        WaitforSingleObject(ProcessInfo.hProcess, INFINITE);
        hAppProcess  := ProcessInfo.hProcess;
        hAppThread   := ProcessInfo.hThread;
      end
else
      raise Exception.Create(ROUTINE_ID          + #10 +  #10 +
                             'Function failure'  + #10 +  #10 +
                             ErrMsg);
  FINALLY
{ Close the handles.
      Kernel objects, like the process and the files
      we created in this case, are maintained by a usage
      count.  So, for cleaning up purposes, we have to
      close the handles to inform the system that we don't
      need the objects anymore }
if hOutputFile <> 0 then CloseHandle(hOutputFile);
if hInputFile <> 0 then CloseHandle(hInputFile);
if hAppThread <> 0 then CloseHandle(hAppThread);
if hAppProcess <> 0 then CloseHandle(hAppProcess);
{ Restore the old cursor }
Screen.Cursor:= OldCursor;
  END;
end;    { CreateDOSProcessRedirected }

 

{=================================================================
  功  能: 提取当前光标下的单词
  参  数:
  返回值:
  备 注: 这个函数能够用来提取当前光标下的单词:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}
function RECharIndexByPos(Memo: TMemo;X, Y: Integer): Integer;
{ function returns absolute character position }
{ for given cursor coordinates }
var
  P: TPoint;
begin
  P := Point(X, Y);
  Result := SendMessage(Memo.Handle,EM_CHARFROMPOS, 0, longint(@P));
end;


{=================================================================
  功  能:
  参  数:
  返回值:
  备 注:
  版 本:
     1.0  2005-10-18 9:05
=================================================================}


var mstrmResFile:TMemoryStream;

procedure ParseResFile;

   function GetTypeName(  bConvertToType : boolean;  piVal : pointer  ) : string;
   var
      w : WORD;
      wc : WideChar;
   begin
      Result := '';

      /
      // Get the type or name,  which is either a integer or a WideString
     
         {Get the first byte of the type/name.  If this is 0xFFFF then the
           following byte is the resource type/name. If it is not, then
           this is the first byte of the first char of the type/name}
      mstrmResFile.Read(  w,  2  );

      if(  w = $FFFF  ) then
      begin
            {Get the type/name}
         mstrmResFile.Read(  w,  2  );

         if(  piVal <> nil  ) then
            integer(piVal^) := w;

         if(  bConvertToType  ) then
         begin
            case(  w  ) of
                1 : Result := 'RT_CURSOR';
                2 : Result := 'RT_BITMAP';
                3 : Result := 'RT_ICON';
                4 : Result := 'RT_MENU';
                5 : Result := 'RT_DIALOG';
                6 : Result := 'RT_STRING';
                7 : Result := 'RT_FONTDIR';
                8 : Result := 'RT_FONT';
                9 : Result := 'RT_ACCELERATOR';
               10 : Result := 'RT_RCDATA';
               12 : Result := 'RT_GROUP_CURSOR';
               14 : Result := 'RT_GROUP_ICON';

               11 : Result := 'RT_MESSAGETABLE';
               16 : Result := 'RT_VERSION';
               17 : Result := 'RT_DLGINCLUDE';
               19 : Result := 'RT_PLUGPLAY';
               20 : Result := 'RT_VXD';
               21 : Result := 'RT_ANICURSOR';
            else
               Result := '??  ' + IntToStr(  w  );
            end;
         end
         else
            Result := IntToStr(  w  );
      end
      else begin
         if(  piVal <> nil  ) then
            integer(piVal^) := -1;

            {'Undo' last read}
         mstrmResFile.Position := mstrmResFile.Position - 2;

         repeat
               {Get a char}
            mstrmResFile.Read(  wc,  sizeof( WideChar )  );
               {Add char to the string}
            Result := Result + wc;

            {Was the last char read the NULL terminator?}
         until(  integer(wc) = 0  );
      end;
   end;


   function GetPadAmount(  iVal : integer  ) : integer;
   begin
      Result := 0;

      while(  (iVal mod 4) <> 0  ) do
      begin
         inc(  iVal  );
         inc(  Result  );
      end;
   end;

var
   li : TListItem;
   sType : string;
   sName : string;
   iTypeVal : integer;
   iDataSize : integer;
   iHeaderSize : integer;
   iHeaderOffset : integer;
begin
      {Clear current items}
   //lv_ResTypes.Items.BeginUpdate;
   //lv_ResTypes.Items.Clear;
   //lv_ResTypes.Items.EndUpdate;

   if(  mstrmResFile = nil  ) then
      Exit;

   mstrmResFile.Position := 0;

      {32bytes for empty record}
   if(  mstrmResFile.Size < 32  ) then
   begin
      ShowMessage(  'File too small'  );
      Exit;
   end;

      {Skip over header}
   mstrmResFile.Position := 32;

      {Parse the file}
   while(  mstrmResFile.Position < mstrmResFile.Size  ) do
   begin
         {Save offset of the header}
      iHeaderOffset := mstrmResFile.Position;

         {Get the data size}
      mstrmResFile.Read(  iDataSize,  4  );
         {Get the header size}
      mstrmResFile.Read(  iHeaderSize,  4  );
         {Get the type}
      sType := GetTypeName(  true,  @iTypeVal  );
         {Get the name}
      sName := GetTypeName(  false,  nil  );

         {Add to the list view}

      //li := lv_ResTypes.Items.Add;
      li.Caption := IntToStr(  iHeaderOffset  );
      li.SubItems.Add(   IntToStr(  iHeaderSize  )   );
      li.SubItems.Add(  sType  );
      li.SubItems.Add(  sName  );
      li.Data := pointer(iTypeVal);

         {Go to end of header}
      mstrmResFile.Position := iHeaderOffset + iHeaderSize;

         {Go to end of data (ie to next header, if there is one)
           Remember to move over any alignment bits}
      mstrmResFile.Position := mstrmResFile.Position + iDataSize + GetPadAmount(  iDataSize  );
   end;
end;


end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值