📄 cmnfunc2.pas
字号:
SE_GROUP_ENABLED = $00000004;
SE_GROUP_USE_FOR_DENY_ONLY = $00000010;
var
Sid: PSID;
CheckTokenMembership: function(TokenHandle: THandle; SidToCheck: PSID;
var IsMember: BOOL): BOOL; stdcall;
IsMember: BOOL;
Token: THandle;
GroupInfoSize: DWORD;
GroupInfo: PTokenGroups;
I: Integer;
begin
if Win32Platform <> VER_PLATFORM_WIN32_NT then begin
Result := True;
Exit;
end;
Result := False;
if not AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
SECURITY_BUILTIN_DOMAIN_RID, DomainAliasRid,
0, 0, 0, 0, 0, 0, Sid) then
Exit;
try
{ Use CheckTokenMembership if available. MSDN states:
"The CheckTokenMembership function should be used with Windows 2000 and
later to determine whether a specified SID is present and enabled in an
access token. This function eliminates potential misinterpretations of
the active group membership if changes to access tokens are made in
future releases." }
CheckTokenMembership := nil;
if Lo(GetVersion) >= 5 then
CheckTokenMembership := GetProcAddress(GetModuleHandle(advapi32),
'CheckTokenMembership');
if Assigned(CheckTokenMembership) then begin
if CheckTokenMembership(0, Sid, IsMember) then
Result := IsMember;
end
else begin
GroupInfo := nil;
if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,
{$IFDEF Delphi3orHigher} Token {$ELSE} @Token {$ENDIF}) then begin
if GetLastError <> ERROR_NO_TOKEN then
Exit;
if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY,
{$IFDEF Delphi3orHigher} Token {$ELSE} @Token {$ENDIF}) then
Exit;
end;
try
GroupInfoSize := 0;
if not GetTokenInformation(Token, TokenGroups, nil, 0, GroupInfoSize) and
(GetLastError <> ERROR_INSUFFICIENT_BUFFER) then
Exit;
GetMem(GroupInfo, GroupInfoSize);
if not GetTokenInformation(Token, TokenGroups, GroupInfo,
GroupInfoSize, GroupInfoSize) then
Exit;
for I := 0 to GroupInfo.GroupCount-1 do begin
if EqualSid(Sid, GroupInfo.Groups[I].Sid) and
(GroupInfo.Groups[I].Attributes and (SE_GROUP_ENABLED or
SE_GROUP_USE_FOR_DENY_ONLY) = SE_GROUP_ENABLED) then begin
Result := True;
Break;
end;
end;
finally
FreeMem(GroupInfo);
CloseHandle(Token);
end;
end;
finally
FreeSid(Sid);
end;
end;
function IsAdminLoggedOn: Boolean;
{ Returns True if the logged-on user is a member of the Administrators local
group. Always returns True on Windows 9x/Me. }
const
DOMAIN_ALIAS_RID_ADMINS = $00000220;
begin
Result := IsMemberOfGroup(DOMAIN_ALIAS_RID_ADMINS);
end;
function IsPowerUserLoggedOn: Boolean;
{ Returns True if the logged-on user is a member of the Power Users local
group. Always returns True on Windows 9x/Me. }
const
DOMAIN_ALIAS_RID_POWER_USERS = $00000223;
begin
Result := IsMemberOfGroup(DOMAIN_ALIAS_RID_POWER_USERS);
end;
function IsMultiByteString(S: String): Boolean;
var
I: Integer;
begin
Result := False;
for I := 1 to Length(S) do
if IsDBCSLeadByte(Ord(S[I])) then begin
Result := True;
Break;
end;
end;
function FontExistsCallback(const lplf: TLogFont; const lptm: TTextMetric;
dwType: DWORD; lpData: LPARAM): Integer; stdcall;
begin
Boolean(Pointer(lpData)^) := True;
Result := 1;
end;
function FontExists(const FaceName: String): Boolean;
var
DC: HDC;
begin
Result := False;
DC := GetDC(0);
try
EnumFonts(DC, PChar(FaceName), @FontExistsCallback, @Result);
finally
ReleaseDC(0, DC);
end;
end;
{$IFNDEF IS_D5}
procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
{$ENDIF}
{$IFNDEF IS_D5}
function SafeLoadLibrary(const Filename: String; ErrorMode: UINT): HMODULE;
var
SaveErrorMode: UINT;
SaveFPUControlWord: Word;
begin
SaveErrorMode := SetErrorMode(ErrorMode);
try
asm
FNSTCW SaveFPUControlWord
end;
try
Result := LoadLibrary(PChar(Filename));
finally
asm
FNCLEX
FLDCW SaveFPUControlWord
end;
end;
finally
SetErrorMode(SaveErrorMode);
end;
end;
{$ENDIF}
function GetUILanguage: LANGID;
{ Platform-independent version of GetUserDefaultUILanguage. May return 0 in
case of failure. }
var
GetUserDefaultUILanguage: function: LANGID; stdcall;
K: HKEY;
S: String;
E: Integer;
begin
GetUserDefaultUILanguage := GetProcAddress(GetModuleHandle(kernel32),
'GetUserDefaultUILanguage');
if Assigned(GetUserDefaultUILanguage) then
{ This function is available on Windows 2000, Me, and later }
Result := GetUserDefaultUILanguage
else begin
if Win32Platform = VER_PLATFORM_WIN32_NT then begin
{ Windows NT 4.0 }
if RegOpenKeyEx(HKEY_USERS, '.DEFAULT\Control Panel\International',
0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
RegQueryStringValue(K, 'Locale', S);
RegCloseKey(K);
end;
end
else begin
{ Windows 95/98 }
if RegOpenKeyEx(HKEY_CURRENT_USER, 'Control Panel\Desktop\ResourceLocale',
0, KEY_QUERY_VALUE, K) = ERROR_SUCCESS then begin
RegQueryStringValue(K, '', S);
RegCloseKey(K);
end;
end;
Val('$' + S, Result, E);
if E <> 0 then
Result := 0;
end;
end;
function RemoveAccelChar(const S: String): String;
var
I: Integer;
begin
Result := S;
I := 1;
while I <= Length(Result) do begin
if Result[I] = '&' then begin
System.Delete(Result, I, 1);
if I > Length(Result) then
Break;
end;
Inc(I, CharLength(Result, I));
end;
end;
function GetTextWidth(const DC: HDC; S: String; const Prefix: Boolean): Integer;
{ Returns the width of the specified string using the font currently selected
into DC. If Prefix is True, it first removes "&" characters as necessary. }
var
Size: TSize;
begin
{ This procedure is 10x faster than using DrawText with the DT_CALCRECT flag }
if Prefix then
S := RemoveAccelChar(S);
GetTextExtentPoint32(DC, PChar(S), Length(S), Size);
Result := Size.cx;
end;
function AddPeriod(const S: String): String;
begin
Result := S;
if (Result <> '') and (PathLastChar(Result)^ > '.') then
Result := Result + '.';
end;
function GetExceptMessage: String;
var
E: TObject;
begin
E := ExceptObject;
if E = nil then
Result := '[ExceptObject=nil]' { should never get here }
else if E is Exception then
Result := AddPeriod(Exception(E).Message) { usual case }
else
Result := E.ClassName; { shouldn't get here under normal circumstances }
end;
function GetPreferredUIFont: String;
{ Gets the preferred UI font. Returns Microsoft Sans Serif, or MS Sans Serif
if it doesn't exist.
Microsoft Sans Serif (which is available on Windows 2000 and later) has two
advantages over MS Sans Serif:
1) On Windows XP, it can display password dots in edit boxes.
2) In my tests on Japanese XP, Microsoft Sans Serif can display Japanese
characters (MS Sans Serif cannot). }
begin
if FontExists('Microsoft Sans Serif') then
Result := 'Microsoft Sans Serif'
else
Result := 'MS Sans Serif';
end;
function IsWildcard(const Pattern: String): Boolean;
begin
Result := (Pos('*', Pattern) <> 0) or (Pos('?', Pattern) <> 0);
end;
function WildcardMatch(const Text, Pattern: PChar): Boolean;
type
TWildcardMatchResult = (wmFalse, wmTrue, wmAbort);
function InternalWildcardMatch(T, P: PChar): TWildcardMatchResult;
begin
while P^ <> #0 do begin
case P^ of
'?': ; { Match any character }
'*': begin
Inc(P);
while P^ = '*' do begin
{ Consecutive stars act just like one }
Inc(P);
end;
if P^ = #0 then begin
{ Trailing star matches everything }
Result := wmTrue;
Exit;
end;
while T^ <> #0 do begin
Result := InternalWildcardMatch(T, P);
if Result <> wmFalse then
Exit;
T := CharNext(T);
end;
Result := wmAbort;
Exit;
end;
else
if not CharCompare(T, P) then begin
Result := wmFalse;
Exit;
end;
end;
T := CharNext(T);
P := CharNext(P);
end;
if T^ = #0 then
Result := wmTrue
else
Result := wmFalse;
end;
begin
Result := (InternalWildcardMatch(Text, Pattern) = wmTrue);
end;
function IntMax(const A, B: Integer): Integer;
begin
if A > B then
Result := A
else
Result := B;
end;
function Win32ErrorString(ErrorCode: Integer): String;
{ Like SysErrorMessage but also passes the FORMAT_MESSAGE_IGNORE_INSERTS flag
which allows the function to succeed on errors like 129 }
var
Len: Integer;
Buffer: array[0..1023] of Char;
begin
Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_ARGUMENT_ARRAY, nil,
ErrorCode, 0, Buffer, SizeOf(Buffer), nil);
while (Len > 0) and (Buffer[Len - 1] in [#0..#32, '.']) do
Dec(Len);
SetString(Result, Buffer, Len);
end;
procedure GetLeadBytes(var ALeadBytes: TLeadByteSet);
var
AnsiCPInfo: TCPInfo;
I: Integer;
J: Byte;
begin
ALeadBytes := [];
GetCPInfo(CP_ACP, AnsiCPInfo);
with AnsiCPInfo do begin
I := 0;
while (I < MAX_LEADBYTES) and ((LeadByte[I] or LeadByte[I+1]) <> 0) do begin
for J := LeadByte[I] to LeadByte[I+1] do
Include(ALeadBytes, Char(J));
Inc(I, 2);
end;
end;
end;
{$IFNDEF IS_D3}
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean;
asm
PUSH ESI
PUSH EDI
MOV ESI,P1
MOV EDI,P2
MOV EDX,ECX
XOR EAX,EAX
AND EDX,3
SHR ECX,1
SHR ECX,1
REPE CMPSD
JNE @@2
MOV ECX,EDX
REPE CMPSB
JNE @@2
@@1: INC EAX
@@2: POP EDI
POP ESI
end;
{$ENDIF}
function DeleteDirTree(const Dir: String): Boolean;
{ Removes the specified directory including any files/subdirectories inside
it. Returns True if successful. }
var
H: THandle;
FindData: TWin32FindData;
FN: String;
begin
if (Dir <> '') and (Pos(#0, Dir) = 0) then begin { sanity/safety checks }
H := FindFirstFile(PChar(AddBackslash(Dir) + '*'), FindData);
if H <> INVALID_HANDLE_VALUE then begin
try
repeat
if (StrComp(FindData.cFileName, '.') <> 0) and
(StrComp(FindData.cFileName, '..') <> 0) then begin
FN := AddBackslash(Dir) + FindData.cFileName;
if FindData.dwFileAttributes and FILE_ATTRIBUTE_READONLY <> 0 then
SetFileAttributes(PChar(FN), FindData.dwFileAttributes and not FILE_ATTRIBUTE_READONLY);
if FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
Windows.DeleteFile(PChar(FN))
else
DeleteDirTree(FN);
end;
until not FindNextFile(H, FindData);
finally
Windows.FindClose(H);
end;
end;
end;
Result := RemoveDirectory(PChar(Dir));
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -