2011. március 31., csütörtök
System and User Locale vs. System and User UI Language
Problem/Question/Abstract:
This sorts out the business of Language IDs and UI Language IDs. Why they are different and how to access them.
Answer:
I became quite confused (easy for me) on the subject of Language ID’s. It turns out, that what I failed to realize is that there is really two, potentially different, languages IDs on a system. Sure, I knew that there is both a default “system” ID and a “user” ID for each defined user on the system but what I didn’t know, was that there is also a system and user UI Language ID.
Windows 32 bit operating systems have a System Locale, which can be retrieved with GetSystemDefaultLangID. System This ID determines which bitmap fonts, and OEM, ANSI and MAC code pages are defaults for the system.
Complementing the system locale default is the user locale default that determines which settings are used for dates, times, currency, numbers, and sort order as a default for each user. The GetUserDefaultLangID retrieves the default value for the current user.
Threads can also have a default locale. New threads default to the default user locale but can be changed with SetThreadLocale and retrieved with GetThreadLocale. The thread locale determines which settings are used for formatting dates, times, currency, numbers, and sort order for the thread.
Eventually, I realized that there is also separate default User Interface (UI) language IDs. These determine the language of menus, dialogs, messages, INF files and help files. The System UI Language is retrieved using GetSystemDefaultUILanguage, while the user UI language is retrieved using GetUseDefaultUILanguage.
Once I finally came to terms with this, not so subtle, distinction between “locals” and “UI languages” I realized that what I needed was the user UI language ID unfortunately none of my copies of Delphi (including Delphi 6) support either GetSystemDefaultUILanguage or GetUseDefaultUILanguage. Even worse, these are relatively new API calls and only first appeared with Windows ME and 2000.
Here is a GetUseDefaultUILanguage I pieced together from various MSDN documents, samples, and factoids. This was written with Delphi 6 and supports OSs from Win95 on up. I’ve only tested it on Windows 2000 so please let me know if it hiccups on Win9x and NT.
Send comments to alecb@o2a.com.
// Helper
function HrFromWin32(dwErr: DWord): HResult;
begin
result := HResultFromWin32(dwErr);
end;
// Helper
function HrFromLastWin32Error: HResult;
var
dw: DWord;
begin
dw := GetLastError;
if dw = 0 then
result := E_Fail
else
result := HrFromWin32(dw);
end;
// Helper
function MAKELANGID(p, s: word): word;
begin
result := (s shl 10) or p;
end;
// The good stuff
function GetUserDefaultUILanguage: LANGID;
type
TGetLang = function: LangID;
THandle = Integer;
var
GetLang: TGetLang;
wUILang: LANGID;
Osv: OSVERSIONINFO;
Reg: TRegistry;
Handle: THandle;
begin
wUILang := 0;
Osv.dwOSVersionInfoSize := sizeof(Osv);
if not GetVersionEx(Osv) then
begin
OleError(HrFromLastWin32Error);
end
// Get the UI language by one of three methods, depending on OS
else if Osv.dwPlatformId <> VER_PLATFORM_WIN32_NT then
begin
// Case 1: Running on Windows 9x. Get the system UI language from registry:
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_USERS;
if Reg.OpenKey('.Default\Control Panel\desktop\ResourceLocale', False) then
begin
wUILang := LangID(Reg.ReadInteger(''));
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end
else if (Osv.dwMajorVersion >= 5.0) then
begin
// Case 2: Running on Windows 2000 or later. Use GetUserDefaultUILanguage
// to find the user's prefered UI language
Handle := LoadLibrary('kernel32.dll');
if Handle <> 0 then
begin
@GetLang := GetProcAddress(Handle, 'GetUserDefaultUILanguage');
if @GetLang <> nil then
wUILang := GetLang;
FreeLibrary(Handle);
end;
end
else
begin
// Case 3: Running on Windows NT 4.0 or earlier. Get UI language
// from locale of .default user in registry:
// HKEY_USERS\.DEFAULT\Control Panel\International\Locale
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_USERS;
if Reg.OpenKey('.Default\Control Panel\desktop\International', False) then
begin
wUILang := LangID(Reg.ReadInteger('Locale'));
Reg.CloseKey;
// Special case these to the English UI.
// These versions of Windows NT 4.0 were enabled only, i.e., the
// UI was English. However, the registry setting
// HKEY_USERS\.DEFAULT\Control Panel\International\Locale was set
// to the respective locale for application compatibility.
if ($0401 = wUILang) or // Arabic
($040D = wUILang) or // Hebrew
($041E = wUILang) then // Thai
begin
wUILang := MakeLangID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
end;
end;
finally
Reg.Free;
end;
end;
result := wUILang;
end;
2011. március 30., szerda
Create and Manage dynamic Forms at Runtime using Class References
Problem/Question/Abstract:
How to dynamicaly create and manage different Forms at runtime in a global manner?
Answer:
If you need to create dynamic forms at runtime and you want to manage them in a global manner, you may have the problem that you don't know how to administrate different form classes. For this case, Delphi comes with special class types of all common objects. But before I go into details, let me create a scenario in which this article may helps you.
"I'll create an application for my customer to let him administrate serveral kinds of data in a local database. Each data category (such as employees, articles, ...) have to been implemented in a specified form with individual edit fields and tools. I don't like to create a MDI bases application (for some reasons) but the customers should have the possibilty to create more than one form for each category (e.g. opens up to 10 forms with customer informations and 3 forms with article informations). He should refer to each form after a while, so all forms have to been non-modular > the customer can hide or minimize each form. In normal MDI application, Delphi helps you to manage the MDI childs form via the 'ActiveMDIChild' property for example, but in non MDI applications you had to manage all child forms by yourself."
To find a workable solution we had to abstract the layer in which we could manage several kinds of forms. Each Delphi form inherites from TCustomForm so our first solution is to create a method who we pass a form reference to memorize - but how to keep such references? By the way, it's also possible to create a form manually and then pass the handle direct to the management component, but we'll create a method which automatically creates each kind of form. At the end of this article we've created a VCL component called TWindowManager which makes all of the discussed stuff, but now - let's start:
function TWindowManager.CreateForm(const Form: TFormClass;
Name: string; Show: Boolean = False): TCustomForm;
begin
if not Form.InheritsFrom(TCustomForm) then
raise Exception.Create('Invalid FormClass - must be a descendant
of TCustomForm!');
Result := TCustomForm(Form.Create(Application));
if Name <> '' then
Result.Name := Name;
// insert code here, to store the reference
if Show then
Result.Show;
end;
Okay, but how to use it? First, we've created a normal Delphi application and added a new form called DynForm1 for example. Delphi automatically creates the following entry in the pas unit:
type
TDynForm1 = class(TForm)
...
end;
For the next step we had to refer to the new unit by included the corresponding unit name to the uses clause. To dynamically create the new form at runtime, you can call the method in a way like:
procedure TMainForm.ButtonDyn1Click(Sender: TObject);
begin
// create a new (dynamic) form.
WindowManager.CreateForm(TDynForm1, True);
end;
Don't marvel about the name WindowManager or TWindowManager in the source examples, I've pasted it direct from the component source I've explained earlier.
Do you notice that we have passed the formclass to the method instead of the name or anythink else? It's possible, because the parameter type of the method is TFormClass which is implemented as TFormClass = class of TForm in Delphi's Forms unit.
Now we need a solution to store the form reference:
type
{ TWindowItem }
PWindowItem = ^TWindowItem;
TWindowItem = packed record
Form: Pointer;
end;
Note:
It's also possible to use a TStringList for example and create items which holds the form handles (or references direct) but it's not a good solutions if you want to search for already existing form (names). Since Version 3 (I'm not sure exactly) Delphi comes with a special container class which gives you some more specific descendants from the TList class. You can use the TObjectList class, derive from it and overwritte the maintenance methods. In this article I use a normal record to store all informations - it's less code to write and you can easily add improved custom informations to store.
The sourcecode of the TWindowManager comes from a Delphi3 implementation I've wrote - if I've some spare time, I'll update it to the newer technology!
Our WindowManager also published a method to directly add already existing form references, so you don't need to create your forms using the CreateForm method:
function TWindowManager.Add(const Form: TCustomForm): Boolean;
var
WindowItem: PWindowItem;
begin
Result := True;
try
New(WindowItem);
WindowItem^.Form := Form;
FWindowList.Add(WindowItem);
except // wrap up
Result := True;
end; // try/except
end;
FWindowList is declared as FWindowList: TList to hold a list of reference records. Followed you'll see to complete sourcode of the TWindowManager - try to understand the individual methods - they are simple. The main trick is the use off class references I've mentioned earlier.
The main component
unit WindowMng;
interface
uses
Classes, Forms, SysUtils, Windows;
type
{ TWinNotifyEvent }
TWinNotifyEvent = procedure(Sender: TObject; Form: TCustomForm) of object;
{ TWindowItem }
// I used a packed record to be more flexible for futher improvements
// which may need to store additional informations.
PWindowItem = ^TWindowItem;
TWindowItem = packed record
Form: Pointer;
end;
{ TWindowManager }
TWindowManager = class(TComponent)
private
{ Private declarations }
FAutoNotification: Boolean;
FLastIndex: Integer;
FWindowList: TList;
FOnFormAdded: TWinNotifyEvent;
FOnFormHandled: TNotifyEvent;
FOnFormRemoved: TWinNotifyEvent;
protected
{ Protected declarations }
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
function GetFormByIndex(Index: Integer): TCustomForm; virtual;
function GetWindowItemByIndex(Index: Integer): PWindowItem; virtual;
function GetWindowItemByForm(const Form: TCustomForm): PWindowItem; virtual;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function Add(const Form: TCustomForm): Boolean; overload;
function Count: Integer;
function CreateForm(const Form: TFormClass; Name: string; Show: Boolean = False):
TCustomForm; overload;
function CreateForm(const Form: TFormClass; Show: Boolean = False): TCustomForm;
overload;
function Exists(const Form: TCustomForm): Boolean;
function Remove(const Form: TCustomForm): Boolean;
function Restore(const Index: Integer): Boolean; overload;
function Restore(const Form: TCustomForm): Boolean; overload;
property Forms[Index: Integer]: TCustomForm read GetFormByIndex; default;
published
{ Published declarations }
property AutoNotification: Boolean read FAutoNotification write FAutoNotification;
property OnFormAdded: TWinNotifyEvent read FOnFormAdded write FOnFormAdded;
property OnFormHandled: TNotifyEvent read FOnFormHandled write FOnFormHandled;
property OnFormRemoved: TWinNotifyEvent read FOnFormRemoved write FOnFormRemoved;
end;
procedure Register;
implementation
// -----------------------------------------------------------------------------
procedure Register;
begin
RegisterComponents('Freeware', [TWindowManager]);
end;
// -----------------------------------------------------------------------------
{ TWindowManager }
constructor TWindowManager.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FAutoNotification := False;
FLastIndex := -1;
FWindowList := TList.Create;
end;
destructor TWindowManager.Destroy;
begin
FWindowList.Free;
inherited Destroy;
end;
procedure TWindowManager.Notification(AComponent: TComponent;
Operation: TOperation);
begin
if (FAutoNotification) and (AComponent <> nil) and (Operation = opRemove)
and (AComponent is TCustomForm) and (Exists(TCustomForm(AComponent))) then
Remove(TCustomForm(AComponent));
inherited Notification(AComponent, Operation);
end;
function TWindowManager.Add(const Form: TCustomForm): Boolean;
var
WindowItem: PWindowItem;
begin
Result := False;
if not Exists(Form) then
try
New(WindowItem);
WindowItem^.Form := Form;
FWindowList.Add(WindowItem);
if FAutoNotification then
Form.FreeNotification(Self);
Result := True;
if assigned(FOnFormAdded) then
FOnFormAdded(Self, Form);
if assigned(FOnFormHandled) then
FOnFormHandled(Self);
except // wrap up
end; // try/except
end;
function TWindowManager.Count: Integer;
begin
Result := FWindowList.Count;
end;
function TWindowManager.CreateForm(const Form: TFormClass; Name: string; Show: Boolean
= False): TCustomForm;
begin
if not Form.InheritsFrom(TCustomForm) then
raise
Exception.Create('Invalid FormClass - must be a descendant of TCustomForm!');
Result := TCustomForm(Form.Create(Application));
if Name <> '' then
Result.Name := Name;
Add(Result);
if Show then
Result.Show;
end;
function TWindowManager.CreateForm(const Form: TFormClass; Show: Boolean = False):
TCustomForm;
begin
Result := CreateForm(Form, '', Show);
end;
function TWindowManager.Exists(const Form: TCustomForm): Boolean;
begin
Result := GetWindowItemByForm(Form) <> nil;
end;
function TWindowManager.GetFormByIndex(Index: Integer): TCustomForm;
var
WindowItem: PWindowItem;
begin
Result := nil;
WindowItem := GetWindowItemByIndex(Index);
if WindowItem <> nil then
Result := TCustomForm(WindowItem^.Form);
end;
function TWindowManager.GetWindowItemByIndex(Index: Integer): PWindowItem;
begin
Result := nil;
if Index < Count then
Result := PWindowItem(FWindowList[Index]);
end;
function TWindowManager.GetWindowItemByForm(const Form: TCustomForm): PWindowItem;
var
iIndex: Integer;
begin
Result := nil;
FLastIndex := -1;
for iIndex := 0 to FWindowList.Count - 1 do
if GetWindowItemByIndex(iIndex)^.Form = Form then
begin
FLastIndex := iIndex;
Result := GetWindowItemByIndex(FLastIndex);
Break;
end;
end;
function TWindowManager.Remove(const Form: TCustomForm): Boolean;
var
WindowItem: PWindowItem;
begin
Result := False;
WindowItem := GetWindowItemByForm(Form);
if WindowItem <> nil then
try
FWindowList.Delete(FLastIndex);
Dispose(WindowItem);
Result := True;
if assigned(FOnFormRemoved) then
FOnFormRemoved(Self, Form);
if assigned(FOnFormHandled) then
FOnFormHandled(Self);
except // wrap up
end; // try/except
end;
function TWindowManager.Restore(const Form: TCustomForm): Boolean;
begin
Result := False;
if (Form <> nil) and (Exists(Form)) then
try
if IsIconic(Form.Handle) then
Form.WindowState := wsNormal;
Form.SetFocus;
Result := True;
except // wrap up
end; // try/except
end;
function TWindowManager.Restore(const Index: Integer): Boolean;
begin
Result := Restore(GetFormByIndex(Index));
end;
end.
To show you the in more detail how to work with this component, followed you'll find a demo application with two additional forms. You don't need to install the component to a package, I'll create it at runtime:
The project file
program WMDemo;
uses
Forms,
MainFrm in 'MainFrm.pas' {MainForm},
WindowMng in 'WindowMng.pas',
DynFrm1 in 'DynFrm1.pas' {DynForm1},
DynFrm2 in 'DynFrm2.pas' {DynForm2};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
The MainForm file
unit MainFrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WindowMng;
type
TMainForm = class(TForm)
ButtonDyn1: TButton;
GroupBoxForms: TGroupBox;
ListBoxForms: TListBox;
ButtonHelloWorld: TButton;
ButtonDyn2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ButtonDyn1Click(Sender: TObject);
procedure ListBoxFormsDblClick(Sender: TObject);
procedure ButtonHelloWorldClick(Sender: TObject);
procedure ButtonDyn2Click(Sender: TObject);
private
{ Private declarations }
WindowManager: TWindowManager;
procedure RedrawFormList(Sender: TObject);
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
uses
DynFrm1, DynFrm2;
{$R *.dfm}
procedure TMainForm.FormCreate(Sender: TObject);
begin
// create WindowManager
WindowManager := TWindowManager.Create(Self);
// enable 'AutoNotification'. If this feature is turned on,
// WindowManager will receive a notification if a form was closed
// by the user, so it can fire events to recorgnize this.
// We use the 'OnFormHandled' event to redraw out ListBox.
WindowManager.AutoNotification := True;
// link event handler to update out ListBox.
WindowManager.OnFormHandled := RedrawFormList;
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
// destroy WindowManager
WindowManager.Free;
end;
procedure TMainForm.RedrawFormList(Sender: TObject);
var
i: Integer;
begin
// get all available forms and display them.
// we also stores the object reference to enable the 'restore' function
// if the user double-clicked on an item.
ListBoxForms.Clear;
for i := 0 to WindowManager.Count - 1 do
ListBoxForms.AddItem(WindowManager.Forms[i].Name, WindowManager.Forms[i]);
end;
procedure TMainForm.ButtonDyn1Click(Sender: TObject);
begin
// create a new (dynamic) form.
WindowManager.CreateForm(TDynForm1, True);
end;
procedure TMainForm.ButtonDyn2Click(Sender: TObject);
begin
// create a new (dynamic) form.
WindowManager.CreateForm(TDynForm2, True);
end;
procedure TMainForm.ListBoxFormsDblClick(Sender: TObject);
var
ClickForm: TCustomForm;
begin
// extract the 'clicked' form.
with ListBoxForms do
ClickForm := TCustomForm(Items.Objects[ItemIndex]);
// restore the form to the top order.
// we used the WindowManager method 'Restore' to be sure
// that the form will be restored also if it was iconized
// before.
WindowManager.Restore(ClickForm);
end;
procedure TMainForm.ButtonHelloWorldClick(Sender: TObject);
begin
// check, if any registered forms exists.
if WindowManager.Count = 0 then
begin
ShowMessage('No dynamic Forms exists - please create one!');
Exit;
end;
// check, if the first available form is 'DynForm1'.
// if true, call the HelloWorld method.
if WindowManager.Forms[0] is TDynForm1 then
TDynForm1(WindowManager.Forms[0]).HelloWorld
else
ShowMessage('The first Form is not a "Dynamic Form I"!');
end;
end.
The MainForm resource file
object MainForm: TMainForm
Left = 290
Top = 255
BorderStyle = bsSingle
Caption = 'MainForm'
ClientHeight = 229
ClientWidth = 510
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
OnCreate = FormCreate
OnDestroy = FormDestroy
DesignSize = (
510
229)
PixelsPerInch = 96
TextHeight = 13
object ButtonDyn1: TButton
Left = 16
Top = 16
Width = 121
Height = 25
Caption = 'Create Dynamic Form I'
TabOrder = 0
OnClick = ButtonDyn1Click
end
object GroupBoxForms: TGroupBox
Left = 16
Top = 56
Width = 481
Height = 169
Anchors = [akLeft, akTop, akRight, akBottom]
Caption = 'Available Forms (Double-Click to restore)'
TabOrder = 1
object ListBoxForms: TListBox
Left = 2
Top = 15
Width = 477
Height = 152
Align = alClient
BorderStyle = bsNone
ItemHeight = 13
ParentColor = True
TabOrder = 0
OnDblClick = ListBoxFormsDblClick
end
end
object ButtonHelloWorld: TButton
Left = 344
Top = 16
Width = 153
Height = 25
Caption = 'Fire ''HelloWorld'' on DynForm1'
TabOrder = 2
OnClick = ButtonHelloWorldClick
end
object ButtonDyn2: TButton
Left = 144
Top = 16
Width = 121
Height = 25
Caption = 'Create Dynamic Form II'
TabOrder = 3
OnClick = ButtonDyn2Click
end
end
The DynForm1 file
unit DynFrm1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TDynForm1 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
procedure HelloWorld;
end;
var
DynForm1: TDynForm1;
implementation
{$R *.dfm}
procedure TDynForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// be sure that our form will be freed.
Action := caFree;
end;
procedure TDynForm1.HelloWorld;
begin
ShowMessage('HelloWorld method was fired!');
end;
end.
The DynForm2 file
unit DynFrm2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TDynForm2 = class(TForm)
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
DynForm2: TDynForm2;
implementation
{$R *.dfm}
procedure TDynForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// be sure that our form will be freed.
Action := caFree;
end;
end.
Hope this article helps you to understand how dynamic forms can be created and managed.
2011. március 29., kedd
How to reindex Paradox tables
Problem/Question/Abstract:
How to reindex Paradox tables
Answer:
There are a number of ways to approach this. One way would be to make a call to the BDE API function DbiRegenIndexes. This insulates you from having to know what indexes exist, if any, the BDE handling all the code for you. Error checking can be handled by examining the return value (type DBIResult) or by using the Check function (defined in the BDE wrapper unit BDE).
procedure TForm1.Button4Click(Sender: TObject);
var
aExclusive, aActive: Boolean;
begin
with Table1 do
begin
aActive := Active;
Close;
aExclusive := Exclusive;
Exclusive := True;
Open;
Check(DbiRegenIndexes(Table1.Handle));
Close;
Exclusive := aExclusive;
Active := aActive;
Check(DbiSaveChanges(Table1.Handle));
end;
end;
As when calling any BDE API function, the BDE API wrapper unit BDE (for Delphi 1, the units DbiTypes, DbiErrs, and DbiProcs) must be referenced in the Uses section of the unit from which the call is to be made. The BDE API function DbiSaveChanges, used here, forces any data changes in memory buffer to be written to disk at that point.
Another way to handle this situation -- if you know at design-time all the indexes that will exist for the table -- would be to iterate through the items in the TIndexDefs object of the TTable component, delete each index (DeleteIndex method), and then add all needed indexes back (AddIndex method).
procedure TForm1.Button3Click(Sender: TObject);
var
aName: string;
i: Byte;
aExclusive, aActive: Boolean;
begin
with Table1 do
begin
aActive := Active;
Close;
aExclusive := Exclusive;
Exclusive := True;
IndexDefs.Update;
i := IndexDefs.Count;
while i > 0 do
begin
aName := IndexDefs.Items[i - 1].Name;
DeleteIndex(aName);
Dec(i);
end;
AddIndex('', 'MainField', [ixPrimary]);
AddIndex('Field1', 'Field1', []);
AddIndex('Field2', 'Field2', []);
IndexDefs.Update;
Exclusive := aExclusive;
Active := aActive;
Check(DbiSaveChanges(Table1.Handle));
end;
end;
When iterating through the items in the TIndexDefs object, the cycling must be backwards, from highest to lowest. This is to account for those table types that have primary indexes. With those table types, deleting a primary index first causes all secondary indexes to be unavailable, which interferes with this iterating based on the TIndexDefs array object contents. This is because a secondary index cannot exist in some table types (such as Paradox) without an existing primary index. For the same reason, when recreating the indexes, the process should start with the primary index and then progress through all secondary indexes (if any are to be created).
If information about the index definitions is not known at design-time, this process becomes emminently more complex. The data from all indexes will need to be saved to memory, the information for all indexes existing simultaneously in memory. This is because a primary index would need to be deleted at some point (to later be rebuilt), destroying references to any secondary indexes (whether retrieval for the secondary indexes takes place before or after deletion of the primary index). To accomplish this, some multi-entity storage structure would need to be created to hold a variable number of elements, one element per index. Each element would need to be able to store the four bits of data that comprise an index's definition: Name (String), Fields (String), Expression (String), and Options (TIndexOptions). An array or a TList object of Pascal records with these data fields would suffice for this purpose.
Once the definition information for all indexes are stored to memory, the succeeding steps are similar to those for the previous method: Delete each index (DeleteIndex) and then recreate each index based on the definition information stored in the array or TList (AddIndex).
2011. március 28., hétfő
Create a thread-safe wrapper class for TCustomIniFile descendents
Problem/Question/Abstract:
How to create a thread-safe wrapper class for TCustomIniFile descendents
Answer:
{Unit ThreadSafeWrapperU:
Declares and implements a simple thread-safe wrapper class as base class
for classes that need to serialize access to some internal object.
Author Dr. Peter Below
Version 1.0 created 18 Oktober 2000
Current revision: 1.0
Last modified: 18 Oktober 2000
Last review: 18.04.2001}
unit ThreadSafeWrapperU;
interface
uses SyncObjs;
type
{This is a class from which classes wrapping some data object in a thread-safe
manner can be derived. The derived class should add a public
Function Lock: Sometype;
that calls InternalLock and then returns a reference for the protected object (kept in a private field ).
Access to the protected object will typically take the form
with wrapper.lock do
try
stuff
finally
wrapper.Unlock;
end;}
TThreadSafeWrapper = class
private
FGuardian: TCriticalSection;
protected
{Enter the critical section}
procedure InternalLock;
public
{Create the critical section}
constructor Create; virtual;
{Destroy the critical section}
destructor Destroy; override;
{Leave the critical section}
procedure Unlock;
end;
implementation
constructor TThreadSafeWrapper.Create;
begin
FGuardian := TCriticalSection.Create;
inherited;
end;
destructor TThreadSafeWrapper.Destroy;
begin
FGuardian.Free;
inherited;
end;
procedure TThreadSafeWrapper.InternalLock;
begin
FGuardian.Acquire;
end;
procedure TThreadSafeWrapper.Unlock;
begin
FGuardian.Release;
end;
end.
{ThreadSafeInifileU:
Implements a thread-safe wrapper class for TCustomInifile descendents.
Author Dr. Peter Below
Version 1.0 created 24.12.2000
Version 1.01 created 25.04.2001, added most of the public inifile methods to wrap
access to the internal inifile
Current revision: 1.01
Last modified: 24.12.2000
Last review: 25.04.2001}
unit ThreadSafeInifileU;
interface
uses
Windows, Classes, ThreadSafeWrapperU, Inifiles;
type
{Enumerated type for TCustomInifile descendents to use}
TIniType = (itRegistryInifile, itInifile, itMemInifile);
{A thread-safe inifile class. The default inifile class used if none is specified in
the constructor is TRegistryInifile}
TThreadsafeInifile = class(TThreadSafeWrapper)
private
FIni: TCustomInifile;
public
constructor Create(aFilename: string; aClass: TIniType = itRegistryInifile;
aAccess: LongWord = KEY_READ or KEY_WRITE); reintroduce;
destructor Destroy; override;
function Lock: TCustomInifile;
function SectionExists(const Section: string): Boolean;
function ReadString(const Section, Ident, Default: string): string;
procedure WriteString(const Section, Ident, Value: string);
function ReadInteger(const Section, Ident: string; Default: Longint): Longint;
procedure WriteInteger(const Section, Ident: string; Value: Longint);
function ReadBool(const Section, Ident: string; Default: Boolean): Boolean;
procedure WriteBool(const Section, Ident: string; Value: Boolean);
function ReadDate(const Section, Ident: string; Default: TDateTime): TDateTime;
function ReadDateTime(const Section, Ident: string; Default: TDateTime):
TDateTime;
function ReadFloat(const Section, Ident: string; Default: Double): Double;
function ReadTime(const Section, Ident: string; Default: TDateTime): TDateTime;
procedure WriteDate(const Section, Ident: string; Value: TDateTime);
procedure WriteDateTime(const Section, Ident: string; Value: TDateTime);
procedure WriteFloat(const Section, Ident: string; Value: Double);
procedure WriteTime(const Section, Ident: string; Value: TDateTime);
procedure ReadSection(const Section: string; Strings: TStrings);
procedure ReadSections(Strings: TStrings);
procedure ReadSectionValues(const Section: string; Strings: TStrings);
procedure EraseSection(const Section: string);
procedure DeleteKey(const Section, Ident: string);
function ValueExists(const Section, Ident: string): Boolean;
end;
implementation
uses
Registry;
{TThreadsafeInifile.Create:
Create the custom ini file descendent.
Parameters:
aFilename: The name to use.
aClass: Defines the class to use.
aAccess: The desired access if aclass is itRegistryInifile.
We have a slight problem here since TCustomInifile.Create is not a virtual constructor.
So we need a somewhat cumbersome Case construct to create the correct class of
TCustomInifile descendent.
Created 24.12.2000 by P. Below}
constructor TThreadsafeInifile.Create(aFilename: string; aClass: TIniType =
itRegistryInifile;
aAccess: DWord = KEY_READ or KEY_WRITE);
begin
inherited Create;
case aClass of
itRegistryInifile:
FIni := TRegistryInifile.Create(aFilename, aAccess);
itInifile:
FIni := TInifile.Create(aFilename);
itMemInifile:
FIni := TMemInifile.Create(aFilename);
end;
end;
{TThreadsafeInifile.Destroy:
Destroy the internal inifile object.
Created 24.12.2000 by P. Below}
destructor TThreadsafeInifile.Destroy;
begin
FIni.Free;
inherited;
end;
{TThreadsafeInifile.Lock:
Aquire access to the ini file and return its reference. Must be paired with an Unlock call!
Created 24.12.2000 by P. Below}
function TThreadsafeInifile.Lock: TCustomInifile;
begin
InternalLock;
Result := FIni;
end;
function TThreadsafeInifile.SectionExists(const Section: string): Boolean;
begin
InternalLock;
try
Result := FIni.SectionExists(Section);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadString(const Section, Ident, Default: string): string;
begin
InternalLock;
try
Result := FIni.ReadString(Section, Ident, Default);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteString(const Section, Ident, Value: string);
begin
InternalLock;
try
FIni.WriteString(Section, Ident, Value);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadInteger(const Section, Ident: string; Default:
Longint): Longint;
begin
InternalLock;
try
Result := FIni.ReadInteger(Section, Ident, Default);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteInteger(const Section, Ident: string; Value:
Longint);
begin
InternalLock;
try
FIni.WriteInteger(Section, Ident, Value);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadBool(const Section, Ident: string; Default: Boolean):
Boolean;
begin
InternalLock;
try
Result := FIni.ReadBool(Section, Ident, Default);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteBool(const Section, Ident: string; Value: Boolean);
begin
InternalLock;
try
FIni.WriteBool(Section, Ident, Value);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadDate(const Section, Ident: string; Default:
TDateTime): TDateTime;
begin
InternalLock;
try
Result := FIni.ReadDate(Section, Ident, Default);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadDateTime(const Section, Ident: string;
Default: TDateTime): TDateTime;
begin
InternalLock;
try
Result := FIni.ReadDatetime(Section, Ident, Default);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadFloat(const Section, Ident: string; Default: Double):
Double;
begin
InternalLock;
try
Result := FIni.ReadFloat(Section, Ident, Default);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ReadTime(const Section, Ident: string; Default:
TDateTime): TDateTime;
begin
InternalLock;
try
Result := FIni.ReadTime(Section, Ident, Default);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteDate(const Section, Ident: string; Value:
TDateTime);
begin
InternalLock;
try
FIni.WriteDate(Section, Ident, Value);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteDateTime(const Section, Ident: string; Value:
TDateTime);
begin
InternalLock;
try
FIni.WriteDatetime(Section, Ident, Value);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteFloat(const Section, Ident: string; Value: Double);
begin
InternalLock;
try
FIni.WriteFloat(Section, Ident, Value);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.WriteTime(const Section, Ident: string; Value:
TDateTime);
begin
InternalLock;
try
FIni.WriteTime(Section, Ident, Value);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.ReadSection(const Section: string; Strings: TStrings);
begin
InternalLock;
try
FIni.ReadSection(Section, Strings);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.ReadSections(Strings: TStrings);
begin
InternalLock;
try
FIni.ReadSections(Strings);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.ReadSectionValues(const Section: string; Strings:
TStrings);
begin
InternalLock;
try
FIni.ReadSectionValues(Section, Strings);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.EraseSection(const Section: string);
begin
InternalLock;
try
FIni.EraseSection(Section);
finally
Unlock;
end;
end;
procedure TThreadsafeInifile.DeleteKey(const Section, Ident: string);
begin
InternalLock;
try
FIni.DeleteKey(Section, Ident);
finally
Unlock;
end;
end;
function TThreadsafeInifile.ValueExists(const Section, Ident: string): Boolean;
begin
InternalLock;
try
Result := FIni.ValueExists(Section, Ident);
finally
Unlock;
end;
end;
end.
2011. március 27., vasárnap
How to use a TControlCanvas in a component
Problem/Question/Abstract:
How to use a TControlCanvas in a component
Answer:
TScrollingPaintBox = class(TScrollingWinControl)
private
FCanvas: TCanvas;
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
property Canvas: TCanvas read FCanvas;
end;
constructor TScrollingPaintBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
end;
destructor TScrollingPaintBox.Destroy;
begin
FCanvas.Free;
inherited Destroy;
end;
A TControlCanvas is important because it creates a DC that belongs to the HWND of the control. Also, override is important on your constructor and destructor to ensure that they are actually called.
2011. március 26., szombat
Extra Color codes for Delphi
Problem/Question/Abstract:
Extra Color codes for Delphi
Answer:
This Article will be updated over time.
Keep checking back!
unit UnitColorConstants;
{-----------------------------------------------------------------
Unit Name: UnitColorConstants
Version: 2.0
Author: Stewart Moss
Creation Date: Jan 31 2002 11:54 pm
Modification Date: Feb 21 2002
Dependancies:
Description:
-- This code is copyright (Jan 31 2002) by Stewart Moss
-- All rights Reserved.
-----------------------------------------------------------------}
interface
uses Graphics;
const
clNicePaleGreen = TColor($CCFFCC);
clPaleRed = TColor($CCCCFF);
clNicePurple = TColor($00E1E100);
clKhaki = TColor($ADAE80);
clMonkeyGreen = TColor($00C0DCC0);
clSkyBlue = TColor($00F1CAA6);
clMedGray = TColor($00A4A0A0);
clCream = TColor($00EFFBFF);
clChocolate = TColor($17335C);
clDarkBrown = TColor($5C3340);
clDarkSlateGrey = TColor($4F4F2F);
clDarkTan = TColor($4F6997);
clDarkWood = TColor($425E85);
clLightWood = TColor($A6C2E9);
clMediumWood = TColor($6480A6);
clNewTan = TColor($9EC7EB);
clSemiSweetChocolate = TColor($26426B);
clSienna = TColor($236B8E);
clWheat = TColor($BFD8D8);
clBrass = TColor($42A6B5);
clBronze = TColor($53788C);
clBronzeII = TColor($3D7DA6);
clCoolCopper = TColor($1987D9);
clCopper = TColor($3373B8);
clQuartz = TColor($F3D9D9);
clFieldSpar = TColor($7592D1);
clGoldenrod = TColor($70DBDB);
clMediumGoldenrod = TColor($AEEAEA);
clBrightGold = TColor($19D9D9);
clGold = TColor($327FCD);
clOldGold = TColor($3BB5CF);
clCoral = TColor($007FFF);
clFirebrick = TColor($23238E);
clIndianRed = TColor($2F2F4E);
clMandarianOrange = TColor($3378E4);
clMediumVioletRed = TColor($9370DB);
clNeonPink = TColor($C76EFF);
clOrangeRed = TColor($0024FF);
clScarlet = TColor($17178C);
clSpicyPink = TColor($AE1CFF);
clThistle = TColor($D8BFD8);
clVioletRed = TColor($9932CC);
clDarkOliveGreen = TColor($2F4F4F);
clForestGreen = TColor($238E23);
clHunterGreen = TColor($215E21);
clMediumForestGreen = TColor($238E6B);
clMediumSeaGreen = TColor($426F42);
clMediumSpringGreen = TColor($00FF7F);
clPaleGreen = TColor($8FBC8F);
clSeaGreen = TColor($688E23);
clSpringGreen = TColor($7FFF00);
clYellowGreen = TColor($32CC99);
clAquamarine = TColor($93DB70);
clCadetBlue = TColor($9F9F5F);
clCornFlowerBlue = TColor($6F4242);
clDarkTurquoise = TColor($DB9370);
clLightBlue = TColor($D9D9C0);
clLightSteelBlue = TColor($BD8F8F);
clMediumAquamarine = TColor($99CD32);
clMediumBlue = TColor($CD3232);
clMediumTurquoise = TColor($DBDB70);
clMidnightBlue = TColor($4F2F2F);
clNeonBlue = TColor($FF4D4D);
clNewMidnightBlue = TColor($9C0000);
clRichBlue = TColor($AB5959);
clSlateBlue = TColor($FF7F00);
clSteelBlue = TColor($8E6B23);
clSummerSky = TColor($DEB038);
clTurquoise = TColor($EAEAAD);
clBlueViolet = TColor($9F5F9F);
clOrchid = TColor($DB70DB);
clDarkPurple = TColor($781F87);
clViolet = TColor($4F2F4F);
clDarkOrchid = TColor($CD3299);
clMediumSlateBlue = TColor($007FFF);
clDarkSlateBlue = TColor($8E236B);
clMediumOrchid = TColor($DB7093);
implementation
end.
Here Is an example of the color codes :-
Violets
Blues
Greens
Reds
Yellows
White, Black and Gray Shades
2011. március 25., péntek
Make a new DBLookupComboBox-Component with OnChange-Event
Problem/Question/Abstract:
DB-Aware Components like TDBEdit have an Event "OnChange". This Event is established in TCustomEdit.
Unfortunately in TDBLookupComboBox there is no OnChange-Event, because this component is not based on TCustomEdit but on TWinControl.
What to do if you want to have an OnChange event in a DBLookupComboBox?
Answer:
DB-Aware Components like TDBEdit have an Event "OnChange". This Event is established in TCustomEdit.
Unfortunately in TDBLookupComboBox there is no OnChange-Event, because this component is not based on TCustomEdit but on TWinControl.
What to do if you want to have an OnChange event in a DBLookupComboBox?
Well, let's build our own component with this event! It's easy because TDBLookupControl established an protected Procedure "KeyValueChanged". It will fired when the property "KeyValue" ist changed.
So we can overwrite this Event in our own Componentent and call a new Event "OnChang".
That's all :-)
type
TMyDBLookupComboBox = class(TDBLookupComboBox)
private
FOnChange: TNotifyEvent;
protected
procedure KeyValueChanged; override;
published
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
implementation
procedure TMyDBLookupComboBox.KeyValueChanged;
begin
inherited;
if Assigned(FOnChange) then
FOnChange(Self);
end;
2011. március 24., csütörtök
How to use the dgMultiSelect option in a TDBGrid
Problem/Question/Abstract:
How to use the dgMultiSelect option in a TDBGrid
Answer:
When you add [dgMultiSelect] to the Options property of a DBGrid, you give yourself the ability to select multiple records within the grid. The records you select are represented as bookmarks and are stored in the SelectedRows property. The SelectedRows property is an object of type TBookmarkList.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables;
type
TForm1 = class(TForm)
Table1: TTable;
DBGrid1: TDBGrid;
Count: TButton;
Selected: TButton;
Clear: TButton;
Delete: TButton;
Select: TButton;
GetBookMark: TButton;
Find: TButton;
FreeBookmark: TButton;
DataSource1: TDataSource;
procedure CountClick(Sender: TObject);
procedure SelectedClick(Sender: TObject);
procedure ClearClick(Sender: TObject);
procedure DeleteClick(Sender: TObject);
procedure SelectClick(Sender: TObject);
procedure GetBookMarkClick(Sender: TObject);
procedure FindClick(Sender: TObject);
procedure FreeBookmarkClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Bookmark1: TBookmark;
z: Integer;
implementation
{$R *.DFM}
{Example of the Count property}
procedure TForm1.CountClick(Sender: TObject);
begin
if DBgrid1.SelectedRows.Count > 0 then
begin
showmessage(inttostr(DBgrid1.SelectedRows.Count));
end;
end;
{Example of the CurrentRowSelected property}
procedure TForm1.SelectedClick(Sender: TObject);
begin
if DBgrid1.SelectedRows.CurrentRowSelected then
showmessage('Selected');
end;
{Example of the Clear Method}
procedure TForm1.ClearClick(Sender: TObject);
begin
dbgrid1.SelectedRows.Clear;
end;
{Example of the Delete Method}
procedure TForm1.DeleteClick(Sender: TObject);
begin
DBgrid1.SelectedRows.Delete;
end;
{This example iterates through the selected rows of the grid and displays
the second field of the dataset.
The Method DisableControls is used so that the DBGrid will not update when the
dataset is changed. The last position of the dataset is saved as a TBookmark.
The IndexOf method is called to check whether or not the bookmark is still existent.
The decision of using the IndexOf method rather than the Refresh method should be determined by the specific application.}
procedure TForm1.SelectClick(Sender: TObject);
var
x: word;
TempBookmark: TBookMark;
begin
DBGrid1.Datasource.Dataset.DisableControls;
with DBgrid1.SelectedRows do
if Count > 0 then
begin
TempBookmark := DBGrid1.Datasource.Dataset.GetBookmark;
for x := 0 to Count - 1 do
begin
if IndexOf(Items[x]) > -1 then
begin
DBGrid1.Datasource.Dataset.Bookmark := Items[x];
showmessage(DBGrid1.Datasource.Dataset.Fields[1].AsString);
end;
end;
end;
DBGrid1.Datasource.Dataset.GotoBookmark(TempBookmark);
DBGrid1.Datasource.Dataset.FreeBookmark(TempBookmark);
DBGrid1.Datasource.Dataset.EnableControls;
end;
{This example allows you to set a bookmark and then search for the bookmarked record
within selected a record(s) within the DBGrid.}
{Sets a bookmark}
procedure TForm1.GetBookMarkClick(Sender: TObject);
begin
Bookmark1 := DBGrid1.Datasource.Dataset.GetBookmark;
end;
{Frees the bookmark}
procedure TForm1.FreeBookmarkClick(Sender: TObject);
begin
if assigned(Bookmark1) then
begin
DBGrid1.Datasource.Dataset.FreeBookmark(Bookmark1);
Bookmark1 := nil;
end;
end;
{Uses the Find method to locate the position of the bookmarked record within
the selected list in the DBGrid}
procedure TForm1.FindClick(Sender: TObject);
begin
if assigned(Bookmark1) then
begin
if DBGrid1.SelectedRows.Find(TBookMarkStr(Bookmark1), z) then
showmessage(inttostr(z));
end;
end;
end.
2011. március 23., szerda
Black-Box Miscellaneous Functions and Procedures
Problem/Question/Abstract:
This is a Black-Box Miscellaneous Library that I have built up over the years (from Turbo Pascal 2.0 days). I have
posted it to this program as many of my components and classes make use of calls to this library. The functions and procedures are too numerous to document here, but they are self explanatory enough. Peruse the source code and I am sure you find something of interest.
Answer:
unit General;
interface
uses Windows, SysUtils, Forms, Dialogs, DBTables, BDE, Classes, DB,
Controls, Registry, Printers, Graphics, DBGrids, ShellAPI,
WinSock, Grids, Math, StdCtrls, NB30, JPEG, Menus,
WinSvc, ComCtrls, ShlObj, Messages, StrUtils;
const CrLf = #13#10; // Carriage Return / Linefeed pair
// Keyboard Char Constants
KY_TAB = #9;
KY_ENTER = #13;
KY_NONE = #0;
KY_BACKSPACE = #8;
KY_COPYRIGHT = #169; // Type ALT 0169 to get ©
KY_REGISTERED = #174; // Type ALT 0174 to get ®
// Extra VK constants missing from Delphi's Windows API interface
VK_NULL = 0;
VK_SEMICOLON = 186;
VK_EQUAL = 187;
VK_COMMA = 188;
VK_MINUS = 189;
VK_PERIOD = 190;
VK_SLASH = 191;
VK_BACKQUOTE = 192;
VK_LEFTBRACKET = 219;
VK_BBACKSLASH = 220;
VK_RIGHTBRACKET = 221;
VK_QUOTE = 222;
// Conts for 0 and 1 for GetDriveType()
DRIVE_UNKNOWN = 0;
DRIVE_UNASSIGNED = 1;
// Range limits on int type vars
MAXSMALLINT = high(smallint);
MINSMALLINT = low(smallint);
MINWORD = low(word);
MAXSHORTINT = high(shortint);
MINSHORTINT = low(shortint);
MAXBYTE = high(byte);
MINBYTE = low(byte);
MAXLONGWORD = high(longword);
MINLONGWORD = low(longword);
MAXSTRING = high(integer);
// Characters that are invalid for file names
INVALID_FILE_CHARS = ['\','/','*','?','<','>','|'];
type
// General usage types
EApplicationFail = class(Exception);
float = double;
TSex = (sxUnknown,sxMale,sxFemale);
TSqlRunMode = (sqlOpen,sqlOpenTerminate,sqlExec,sqlExecTerminate);
TJustifyMenuMode = (jsmRight,jsmLeft,jsmToggle);
TCharTypes = (chAlpha,chDigit,chHex,chUpper,chLower,chWhitespace,
chPunctuation,chSign,chAnsi,chControl,chOperator);
TCharTypesSet = set of TCharTypes;
TCpuFeature = (cpuNoCPUID,cpuNonIntel,cpuOnChipFPU,
cpuVirtualModeExtensions,cpuDebuggingExtensions,
cpuPageSizeExtensions,cpuTimeStampCounter,
cpuModelSpecificRegisters,cpuPhysicalAddressExtensions,
cpuMachineCheckExtensions,cpuCMPXCHG8B,cpuOnChipAPIC,
cpuFastSystemCall,cpuMemoryRangeRegisters,cpuPageGlobalEnable,
cpuMachineCheckArchitecture,cpuConditionalMoveInstruction,
cpuPageAttributeTable,cpu32bitPageSzExtension,
cpuProcessorSerialNum,cpuMMXTechnology,cpuFastFloatingPoint,
cpuSIMDExtensions);
TCpuFeatures = set of TCpuFeature;
function BDEinstalled(TerminateOnErr : boolean = false;
ShowErrorDlg : boolean = false;
InfoList : TStrings = nil) : string;
function CopyFrom(const S : string; StartPos : integer) : string;
function DefaultMessagingProfile : string;
function DeleteTree(const SrcPath : string) : boolean;
function FontInstalled(Const FontName : string) : boolean;
function Darker(Color : TColor; Percent : integer) : TColor;
function MixColors(C1,C2 : TColor) : TColor;
function Lighter(Color : TColor; Percent : integer) : TColor;
function ContrastColor(Color : TColor) : TColor;
function GetDAOversion : integer; overload;
function GetDAOversion(SList : TStrings) : integer; overload;
function StuffStr(const SrcStr,DestStr : string; Position : integer) : string;
function BrowseFolder(const title : string;Flags : longword = 0) : string;
function ServiceStart(aMachine,aServiceName : string) : boolean;
function ServiceStop(aMachine,aServiceName : string) : boolean;
function ServiceGetStatus(sMachine, sService: string ): DWord;
function ServiceGetStatusName(sMachine,sService: string ): string;
function WinCalcValue : string;
function MemCompare(P1,P2 : pointer; Len : integer) : integer;
function SearchTree(StartDir,FileToFind : string;
out FileNamePath : string) : boolean;
function StrInList(const SrcStr : string; List : TStrings) : boolean;
function AndEqual(Value,AndValue : longword) : boolean;
function BiosDate : string;
function BiosID : string;
function toString(Value : Variant) : string;
function IntToBase(Value : integer; Base : byte;Digits : byte = 0): string;
function BaseToint(Value : string; Base : byte) : integer;
function StartsWith(const SourceStr,TargetStr : string;
IgnoreCase : boolean = false) : boolean;
function EndsWith(const SourceStr,TargetStr : string;
IgnoreCase : boolean = false) : boolean;
function GetOSName : string;
function NetFindNextUnmapped : char;
function NetMappedName(LocalDrive : char) : string;
function NetUnMapDrive(LocalDrive : char) : dword;
function NetMapDrive(LocalDrive : char; const RemoteDrivePath : string;
UserName : string = ''; Password : string = '') : dword;
function GetLastWinErr(ShowDialog : boolean = true;
ErrNum : integer = 0) : string;
function GetMACAddress: string;
function GetParamVal(const TaggedParm : string;
IgnoreCase : boolean = true) : string;
function GetCpuSerialNum : string;
function StrToSex(SexStr : string) : TSex;
function SexToStr(Sex : TSex) : string;
function StrToFileName(const FileName : string; ReplaceInvalidWith : char = '_') : string;
function RoundIt(Value : extended; Decimals : integer = 2) : extended;
function Sign(Value : extended) : integer;
function LastChar(StrVar : string) : char;
function IsNullStr(const StrVar : string) : boolean;
function PosEx(const SubStr,TargetS : string; StartPos : integer = 1;
IgnoreCase : boolean = false) : integer;
function PosCount(const SubStr,TargetS : string; CountIndex : integer = 1) : integer;
function DeskTopLVhandle : THandle;
function CharTypeSet(Ch : char) : TCharTypesSet;
function NumToLetters(Number : extended; Currency : string = 'Rands';
Cents : string = 'Cents') : string;
function Discount(Value : double; PercentDisc : double) : double; overload;
function Discount(Value : double; PercentDisc : double;
out DiscAmnt : double) : double; overload;
function MarkUp(Value : double; PercentMarkup : double) : double; overload;
function MarkUp(Value : double; PercentMarkup : double;
out MarkupAmnt : double) : double; overload;
function GPpercent(Cost,Sell : double) : double; overload;
function GPpercent(Cost,Sell : double;
out MarkupPercent : double) : double; overload;
function IntToBin(IValue : Int64; NumBits : word = 64) : string;
function BinToInt(BinStr : string) : Int64;
function HexToInt(HexStr : string) : Int64;
function CPUSpeed : integer;
function MyIPAddress : string;
function DateStamp : string;
function FmtStrToInt(IntString : string) : integer;
function FmtStrToIntDef(IntString : string; DefValue : integer) : integer;
function FmtStrToFloat(FloatString : string) : extended;
function StrZero(Value : integer; Len : byte) : string;
function Pad(const S : string; L : byte; FillChar : char = ' ') : string;
function PadL(const S : string; L : byte; FillChar : char = ' ') : string;
function PadR(const S : string; L : byte; FillChar : char = ' ') : string;
function Space(N : byte) : string;
function Replicate(C : char; L : word) :string;
function Proper(StrVar : string) :string;
function Zdiv(N1,N2 : integer) : integer; overload;
function Zdiv(N1,N2 : extended) : extended; overload;
function Empty(const Arg : array of const) : boolean;
function AlphaOnly(StrVar : string) : string;
function NumericOnly(StrVar : string) : string;
function FileInUse(FileName : string) : boolean;
function GetLogonName(UCase : boolean = true) : string;
function GetDomainName(User : string = '') : string;
function GetDiskSerialNum(DriveLetter : char; HexValue : boolean = false) : string;
function GetExePath : string;
function GetExeName : string;
function GetExeFile : string;
function GetAliasPath(Aname : string) : string;
function ExtractCommaDelim(var Source : string) : string;
function ExtractField(var Source : string; Delimiter : string) : string; overload;
function ExtractField(StrList : TStrings; const Source : string; Delimiter : string) : string; overload;
function StripParen(const StrVar : string) : string;
function WinExecWait(const ChangeDir : string; const ExecutableFile : string;
Params : string = ''; WindowStyle : LongWord = SW_SHOWNORMAL) : boolean;
function FileVersion(const FileName : string = '') : string;
function FileVersionInfo(const FieldName : string; const FileName : string = '') : string;
function FileVersionLanguage(const FileName : string = '') : string;
function UnixPathToDosPath(FName : string) : string;
function DosPathToUnixPath(FName : string) : string;
function EnCryptString(StrVar : string; EncryptKey : string = '') : string;
function DeCryptString(StrVar : string; EncryptKey : string = '') : string;
function CharCount(SearchChar : char; Buffer : string) : integer;
function RPos(SubStr : string; S : string) : integer;
function GetUniqueFileName : string;
function IsNetworked : boolean;
function CheckBackSlash(Path : string; MustHave : boolean = true) : string;
function ConfirmDlg(MessageStr : string; DoBeep : boolean = true) : boolean;
function DateToStr4(TargetDate : TDateTime) : string;
function StrToDate4(DateStr : string; ErrMessage : boolean = true) : TDateTime;
function StrToDateTime4(const DateTimeStr : string) : TDateTime;
function StrToDateTime(DateStr : string) : TDateTime;
function DateToStr(TargetDate : TDateTime) : string;
function StrToDate(DateStr : string) : TDateTime;
function IsDefaultPrinter(Showmessage : boolean = true) : boolean; overload;
function IsDefaultPrinter(out DefaultPrinterName : string;
Showmessage : boolean = true) : boolean; overload;
function FontStyleToInt(FS : TFontStyles) : integer;
function IntToFontStyle(Num : integer) : TFontStyles;
function WindowsDir : string;
function WindowsSystemDir : string;
function ComputerName : string;
function GetFileTimes(FileName : string;
out Created : TDateTime;
out Modified : TDateTime;
out Accessed : TDateTime) : boolean;
function CopyPdxTable(SrcTable,DstTable : string;
out ErrMess : string;
Overwrite : boolean = true) : boolean;
function iif(const Condition: Boolean; const TruePart, FalsePart: string): string; overload;
function iif(const Condition: Boolean; const TruePart, FalsePart: Char): Char; overload;
function iif(const Condition: Boolean; const TruePart, FalsePart: Byte): Byte; overload;
function iif(const Condition: Boolean; const TruePart, FalsePart: Integer): Integer; overload;
function iif(const Condition: Boolean; const TruePart, FalsePart: Cardinal): Cardinal; overload;
function iif(const Condition: Boolean; const TruePart, FalsePart: extended): extended; overload;
function iif(const Condition: Boolean; const TruePart, FalsePart: Boolean): Boolean; overload;
function iif(const Condition: Boolean; const TruePart, FalsePart: Pointer): Pointer; overload;
function iif(const Condition: Boolean; const TruePart, FalsePart: Int64): Int64; overload;
function GetCpuFeatures(FeatureList : TStrings = nil) : TCpuFeatures;
function BitIsSet(WordValue : word; BitNum : word) : boolean; overload;
function BitIsSet(WordValue : word; BitNums : array of word) : boolean; overload;
procedure LoadCLSID(StringList : TStrings; Separator : char = '*';
IncludeVersionIndependent : boolean = true);
procedure StrGridToHTML(const FileName : string; StrGrid : TStringGrid;
const Heading : string = '';
TextColor : TColor = clBlack;
TableBgColor : TColor = clAqua);
procedure StrGridToRTF(const Filename : string; SG : TStringGrid);
procedure DisableTaskManager(const State : boolean);
procedure DisableLockWorkStation(const State : boolean);
procedure DisableChangePassword(const State : boolean);
procedure DisableLogoff(const State : boolean);
procedure DisableShutdown(const State : boolean);
procedure DisableRegistryTools(const State : boolean);
procedure DisableScreenSaver(const State : boolean);
procedure SetScreenSaverTimeOut(const TimeMilSec : integer);
procedure PrintStrGrid(StringGrid : TStringGrid; ShowSetupDialog : boolean = true);
procedure SetCheckBoxCheck(cb : TCheckBox; Checked : boolean);
procedure GoURL(const WebUrl : string);
procedure SetTrackbarNarrow(TB : TTrackBar);
procedure CpyRecByName(Src,Dst : TDataSet);
procedure CpyRecByNum(Src,Dst : TDataSet);
procedure NetDomainList(StringList : TStrings);
procedure SetBit(var WordValue : word; BitNum : word); overload;
procedure SetBit(var WordValue : word; BitNums : array of word); overload;
procedure ClearBit(var WordValue : word; BitNum : word); overload;
procedure ClearBit(var WordValue : word; BitNums : array of word); overload;
procedure ToggleBit(var WordValue : word; BitNum : word); overload;
procedure ToggleBit(var WordValue : word; BitNums : array of word); overload;
procedure CreateTreeMenus(Path : string; Menu : TMainMenu;
Root : TMenuItem; ListImage : TImageList );
procedure JustifyMenuItem(Menu : TMainMenu; MenuItem : TMenuItem;
Justify : TJustifyMenuMode = jsmRight);
procedure ScreenShot(X1,X2,Y1,Y2 : integer; BMap : TBitMap); overload;
procedure ScreenShot(BMap : TBitMap); overload;
procedure ScreenShot(X1,X2,Y1,Y2 : integer; JMap : TJPEGImage); overload;
procedure ScreenShot(JMap : TJPEGImage); overload;
procedure AllowMultiline(theControl : TWinControl);
procedure ShredFile(const FileName : string);
procedure QueryToStrGrid(Query : TQuery; StrGrid : TStringGrid; Titles : boolean = true);
procedure GetScreenXY(TargetControl : TControl; out X : integer;
out Y : integer);
procedure VarToStr(var Source; Count : integer; out StrVar : string;
ReplaceChar0With : char = #0);
procedure StrToVar(const StrVar : string; out UtypedVar);
procedure SetLastChar(var StrVar : string; CharValue : char);
procedure GetWindowsList(TS : TStrings);
procedure SwapMem(var Source,Dest; Len : integer);
procedure StringScan(const Buffer : string; const Mask : string; LinesList : TStrings);
procedure ErrorDlg(MessageStr : string; DoBeep : boolean = true);
procedure InfoDlg(MessageStr : string; DoBeep : boolean = true);
procedure WarningDlg(MessageStr : string; DoBeep : boolean = true);
procedure SetMaxSize(Form : TForm);
procedure HaltApplication(UserMessage : string; ShowMessage : boolean = false);
procedure Delay(ms : longword);
procedure LoadGridSettings(FileName : string; Grid : TDBGrid; DefaultToExePath : boolean = true);
procedure SaveGridSettings(FileName : string; Grid : TDBGrid; DefaultToExePath : boolean = true);
procedure SetAutoStart(AppTitleKey : string; Status : boolean = true);
procedure RemoveFormCaption(Form : TForm);
procedure SortStr(var StrVar : string);
procedure ReplaceChars(var StrVar : string; ThisChar,WithChar : char;
IgnoreCase : boolean = false);
procedure IncLimit(var X : longint; Limit : longint;
RollOverVal : longint = 0; IncBy : longint = 1);
procedure DecLimit(var X : longint; Limit : longint;
RollUnderVal : longint = 0; DecBy : longint = -1);
procedure TextOutAngle(ParentCanvas : TCanvas;
X,Y : integer;
const FontName : string;
FontSize,Angle : integer;
const Txt : string;
Color : TColor = clBlack;
Transparent : boolean = true);
procedure AnimateShowWin(Form : TForm; dwFlags : DWORD; dwTime : DWORD = 300);
procedure AnimateHideWin(Form : TForm; dwFlags : DWORD; dwTime : DWORD = 300);
procedure DisableKeyboard;
procedure EnableKeyboard;
{ ======================================================================== }
implementation
const ENCRYPT_KEY = 'Put some string Here That is Meaningfull';
// Win ver constants
cOsUnknown : integer = -1;
cOsWin95 : integer = 0;
cOsWin98 : integer = 1;
cOsWin98SE : integer = 2;
cOsWinME : integer = 3;
cOsWinNT : integer = 4;
cOsWin2000 : integer = 5;
cOsWhistler : integer = 6;
var oldHook : HHook; // Used by keyboard enable/disable
// Keyboard intercept routine
function KeyBoardHook(Code : integer; wParam : word; lParam: longint) : longint;
begin
if (Code < 0) then
Result := CallNextHookEx(oldHook,Code,wParam,lParam)
else
Result := 1;
end;
procedure DisableKeyboard;
begin
oldHook := SetWindowsHookEx(WH_KEYBOARD,@KeyBoardHook,HInstance,0);
end;
procedure EnableKeyboard;
begin
if (oldHook <> 0) then begin
UnhookWindowshookEx(oldHook);
oldHook := 0;
end;
end;
// =============================================
// Simple password encode/decode routines
// Changed to EncryptString and DecryptString
// was .....
// function EncodePassword(Pass : string) : string;
// function DecodePassword(Pass : string) : string;
// =============================================
function EnCryptString(StrVar : string; EncryptKey : string = '') : string;
var Cmd,Key : string;
i,KIdx : integer;
Ch : byte;
begin
Cmd := StringOfChar(' ',length(StrVar));
KIdx := 1;
if EncryptKey = '' then Key := ENCRYPT_KEY else Key := EncryptKey;
for i := 1 to length(StrVar) do begin
Ch := byte(StrVar[i]) xor byte(Key[KIdx]);
if Ch = 0 then Ch := 255;
Cmd[i] := char(Ch);
inc(KIdx);
if KIdx > length(Key) then KIdx := 1;
end;
Result := Cmd;
end;
function DeCryptString(StrVar : string; EncryptKey : string = '') : string;
var Cmd,Key : string;
Ch : byte;
i,KIdx : integer;
begin
Cmd := StringOfChar(' ',length(StrVar));
KIdx := 1;
if EncryptKey = '' then Key := ENCRYPT_KEY else Key := EncryptKey;
for i := 1 to length(StrVar) do begin
Ch := byte(StrVar[i]);
if Ch = 255 then Ch := 0;
Cmd[i] := char(Ch xor byte(Key[KIdx]));
inc(KIdx);
if KIdx > length(Key) then KIdx := 1;
end;
Result := Cmd;
end;
// ===================================
// Convert a string to a TSex var
// ===================================
function StrToSex(SexStr : string) : TSex;
var BChar : char;
Cmd : TSex;
begin
Cmd := sxUnknown;
if (length(SexStr) > 0) then begin
BChar := UpCase(SexStr[1]);
case BChar of
'M' : Cmd := sxMale;
'F' : Cmd := sxFemale;
end;
end;
Result := Cmd;
end;
// ==================================
// Convert a TSex var to a string
// ==================================
function SexToStr(Sex : TSex) : string;
var Cmd : string;
begin
Cmd := 'Unknown';
case Sex of
sxMale : Cmd := 'Male';
sxFemale : Cmd := 'Female';
end;
Result := Cmd;
end;
// ===============================================
// Convert a string to a valid file name
// Invalid chars are replaced by ReplaceWith
// Default replace char is UNDER_LINE
// ===============================================
function StrToFileName(const FileName : string;
ReplaceInvalidWith : char = '_') : string;
var Cmd : string;
i : integer;
begin
Cmd := FileName;
for i := 1 to length(FileName) do
if Cmd[i] in INVALID_FILE_CHARS then
Cmd[i] := ReplaceInvalidWith;
Result := Cmd;
end;
// ===================================
// Return Count of a char in a string
// ===================================
function CharCount(SearchChar : char; Buffer : string) : integer;
var C,i : integer;
begin
C := 0;
if length(Buffer) > 0 then
for i := 1 to length(Buffer) do
if Buffer[i] = SearchChar then inc(C);
Result := C;
end;
// ====================================================
// Str to Numeric Functions same as Delphi's StrToInt,
// StrToIntDef,StrToFloat.
// allows formatted strings eg. 9,143,654
// ====================================================
function FmtStrToInt(IntString : string) : integer;
var i : byte;
s : string;
sign : integer;
begin
s := '';
sign := 1;
for i := 1 to length(IntString) do begin
if IntString[i] = '-' then sign := -1;
if IntString[i] in ['0'..'9'] then s := s + IntString[i];
end;
Result := StrToInt(s) * sign;
end;
function FmtStrToIntDef(IntString : string; DefValue : integer) : integer;
var i : byte;
s : string;
sign,v : integer;
begin
s := '';
sign := 1;
for i := 1 to length(IntString) do begin
if IntString[i] = '-' then sign := -1;
if IntString[i] in ['0'..'9'] then s := s + IntString[i];
end;
try
v := StrToInt(s) * sign;
except
v := DefValue;
end;
Result := v;
end;
function FmtStrToFloat(FloatString : string) : extended;
var i : byte;
s : string;
sign : extended;
begin
s := '';
sign := 1.0;
for i := 1 to length(FloatString) do begin
if FloatString[i] = '-' then sign := -1.0;
if FloatString[i] in ['0'..'9','.'] then s := s + FloatString[i];
end;
try
Result := StrToFloat(s) * sign;
except
Result := 0;
end;
end;
{ ===================================== }
{ Execute a program like WINEXE() }
{ But WAIT for the program to terminate }
{ before returning to the calling app }
{ Returns true or false. }
{ ===================================== }
function WinExecWait(const ChangeDir : string;
const ExecutableFile : string;
Params : string = '';
WindowStyle : LongWord = SW_SHOWNORMAL) : boolean;
var p : TProcessInformation;
s : TStartupInfo;
PParams : PChar;
Cmd : boolean;
CDir : string;
begin
CDir := GetCurrentDir;
s.cb := SizeOf(TStartupInfo);
s.wShowWindow := WindowStyle;
s.lpDesktop := nil;
s.dwFlags := STARTF_USESHOWWINDOW;
s.lpReserved := nil;
s.lpTitle := nil;
s.cbReserved2 := 0;
s.lpReserved2 := nil;
if trim(ChangeDir) <> '' then SetCurrentDir(ChangeDir);
if trim(Params) = '' then
PParams := PChar(ExecutableFile)
else begin
// if Params[1] <> ' ' then Params := ' ' + Params; W2000 ???
if Params[1] <> ' ' then Params := '"' + ExecutableFile + '" ' + Params ;
PParams := PChar(Params);
end;
// Following does not work in W2000
// if CreateProcess(PChar(ExecutableFile),PParams,nil,nil,true,0,nil,nil,s,p) then begin
if CreateProcess(nil,PParams,nil,nil,true,0,nil,nil,s,p) then begin
WaitForSingleObject(p.hProcess,INFINITE);
CloseHandle(p.hProcess);
CloseHandle(p.hThread);
Cmd := true;
end
else
Cmd := false;
SetCurrentDir(CDir);
Result := Cmd;
end;
{ ============================== }
{ Convert Unix Path to Dos Path }
{ and vice-versa }
{ ============================== }
function UnixPathToDosPath(FName : string) : string;
var i : integer;
begin
for i := 1 to length(FName) do if FName[i] = '/' then FName[i] := '\';
Result := FName;
end;
function DosPathToUnixPath(FName : string) : string;
var i : integer;
begin
for i := 1 to length(FName) do if FName[i] = '\' then FName[i] := '/';
Result := FName;
end;
// =============================================================
// Return the file version of a
// Win32 executable file. See FileVersionInfo for additional }
// =============================================================
function FileVersion(const FileName : string = '') : string;
var V1,V2,V3,V4 : word;
VerInfoSize, VerValueSize, Dummy : DWORD;
VerInfo : Pointer;
VerValue : PVSFixedFileInfo;
FName : string;
begin
try
if FileName = '' then
FName := GetExePath + GetExeFile
else
FName := trim(FileName);
VerInfoSize := GetFileVersionInfoSize(PChar(FName), Dummy);
GetMem(VerInfo, VerInfoSize);
try
GetFileVersionInfo(PChar(FName), 0, VerInfoSize, VerInfo);
VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize);
with VerValue^ do begin
V1 := dwFileVersionMS shr 16;
V2 := dwFileVersionMS and $FFFF;
V3 := dwFileVersionLS shr 16;
V4 := dwFileVersionLS and $FFFF;
end;
finally
FreeMem(VerInfo, VerInfoSize);
end;
Result := IntToStr(V1) + '.' + IntToStr(V2) + '.' +
IntToStr(V3) + '.' + IntToStr(V4);
except
Result := '';
end;
end;
// =================================================================
// Get info form file version eg. "Comments", "ProductName" etc.
// See Project/Options/Version Info for available Fields
// =================================================================
function FileVersionInfo(const FieldName : string;
const FileName : string = '') : string;
var VerInfoSize,VerValueSize,Dummy : DWORD;
Lang : string;
VerInfo : Pointer;
VerValue : ^word;
VerChar : PChar;
FName : string;
begin
VerChar := nil;
try
if FileName = '' then
FName := GetExePath + GetExeFile
else
FName := trim(FileName);
VerInfoSize := GetFileVersionInfoSize(PChar(FName),Dummy);
GetMem(VerInfo,VerInfoSize);
try
GetFileVersionInfo(PChar(FName),0,VerInfoSize,VerInfo);
VerQueryValue(VerInfo,'\VarFileInfo\Translation',
Pointer(VerValue),VerValueSize);
Lang := IntToHex(VerValue^,4);
inc(VerValue);
Lang := Lang + IntToHex(VerValue^,4);
VerQueryValue(VerInfo,PChar('\StringFileInfo\' + Lang + '\' + FieldName),
Pointer(VerChar),VerValueSize);
if VerChar <> nil then begin
Result := VerChar;
SetLength(Result,StrLen(PChar(Result)))
end
else
Result := '';
finally
FreeMem(VerInfo,VerInfoSize);
end;
except
Result := '';
end;
end;
function FileVersionLanguage(const FileName : string = '') : string;
var VerInfoSize,VerValueSize,Dummy : DWORD;
VerInfo : Pointer;
Lang : string;
VerValue : ^DWORD;
FName : string;
begin
SetLength(Lang,257);
try
if FileName = '' then
FName := GetExePath + GetExeFile
else
FName := trim(FileName);
VerInfoSize := GetFileVersionInfoSize(PChar(FName),Dummy);
GetMem(VerInfo,VerInfoSize);
try
GetFileVersionInfo(PChar(FName),0,VerInfoSize,VerInfo);
VerQueryValue(VerInfo,'\VarFileInfo\Translation',
Pointer(VerValue),VerValueSize);
VerLanguageName(VerValue^,PChar(Lang),256);
Result := Lang;
SetLength(Result,StrLen(PChar(Result)))
finally
FreeMem(VerInfo,VerInfoSize);
end;
except
Result := '';
end;
end;
{ ==================================== }
{ Return a string with it's }
{ Parenthesis stripped. }
{ eg. "Freddy" will return Freddy }
{ [Koos] will return Koos }
{ ==================================== }
function StripParen(const StrVar : string) : string;
begin
Result := copy(StrVar,2,length(StrVar)-2);
end;
{ ==================================== }
{ Return a boolean of state of file }
{ false = File is NOT open on network }
{ true = file is open on network }
{ ==================================== }
function FileInUse(FileName : string) : boolean;
var F : file;
IsInUse : boolean;
begin
AssignFile(F,FileName);
try
Reset(F);
CloseFile(F);
IsInUse := false;
except
IsInUse := true;
end;
Result := IsInUse;
end;
// =================================================
// Return true/false if string is in string list
// =================================================
function StrInList(const SrcStr : string; List : TStrings) : boolean;
var Cmd : boolean;
i : integer;
CmpStr : string;
begin
Cmd := false;
CmpStr := UpperCase(trim(SrcStr));
for i := 0 to List.Count - 1 do begin
if CmpStr = Uppercase(trim(List[i])) then begin
Cmd := true;
break;
end;
end;
Result := Cmd;
end;
{ =========================== }
{ Return a string of N spaces }
{ =========================== }
function Space(N : byte) : string;
begin
Space := StringOfChar(' ',N);
end;
{ ========================================== }
{ Replicate returns a string of C that is }
{ L characters long. OBSOLETE }
{ Use StringofChar instead !!!!!!!
{ ========================================== }
function Replicate(C : char; L : word) :string;
begin
Result := StringOfChar(C,L);
end;
{ =================================================== }
{ Returns a string left padded with zeros for L bytes }
{ =================================================== }
function StrZero(Value : integer; Len : byte) : string;
begin
Result := FormatFloat(StringOfChar('0',Len),Value);
end;
{ ======================================= }
{ Right justify a string an pad remaining }
{ space with blanks or truncate if < L }
{ ======================================= }
function PadR(const S : string; L : byte; FillChar : char = ' ') : string;
begin
Result := Pad(S,L,FillChar);
end;
function Pad(const S : string; L : byte; FillChar : char = ' ') : string;
var Cmd : string;
begin
Cmd := trim(S);
if L < length(Cmd) then
Cmd := Copy(Cmd,1,L)
else
Cmd := Cmd + StringOfChar(FillChar,L - length(Cmd));
Result := Cmd;
end;
{ ====================================== }
{ Right justify a string }
{ ====================================== }
function PadL(const S : string; L : byte; FillChar : char = ' ') : string;
var Cmd : string;
begin
Cmd := trim(S);
if L < length(Cmd) then
Cmd := Copy(Cmd,1,L)
else
Cmd := StringOfChar(FillChar,L - length(S)) + S;
Result := Cmd;
end;
// =====================================
// Like copy, but does not need LEN
// =====================================
function CopyFrom(const S : string; StartPos : integer) : string;
begin
Result := copy(S,StartPos,MAXSTRING);
end;
{ ==================================== }
{ Return a proper name from a var }
{ ==================================== }
function Proper(StrVar : string) :string;
var Upit : boolean;
RetStr : string;
I,Olen : word;
S : string[1];
begin
Upit := true;
RetStr := '';
Olen := length(StrVar);
StrVar := trim(Lowercase(StrVar));
for I := 1 to length(StrVar) do begin
S := copy(StrVar,I,1);
if Upit or (S = ' ') or (S = '.') then begin
S := upcase(S[1]);
Upit := (S = ' ') or (S = '.');
end;
RetStr := RetStr + S;
end;
Result := Pad(RetStr,Olen);
end;
{ =================================== }
{ Eliminate DIVIDE by zero error }
{ of two reals. }
{ Zdiv returns 0 if divisor is zero }
{ Overload to accomodate int and real }
{ =================================== }
function Zdiv(N1,N2 : extended) : extended; overload;
var Cmd : extended;
begin
Cmd := 0.00;
if N2 <> 0.0 then Cmd := N1 / N2;
Result := Cmd;
end;
function Zdiv(N1,N2 : integer) : integer; overload;
var Cmd : integer;
begin
Cmd := 0;
if N2 <> 0 then Cmd := N1 div N2;
Result := Cmd;
end;
{ ================================ }
{ Return true if var type is empty }
{ param passed as [Xvar] }
{ ================================ }
function Empty(const Arg : array of const) : boolean;
begin
Result := false;
case Arg[0].VType of
vtInteger : if Arg[0].VInteger = 0 then Result := true;
vtBoolean : if not Arg[0].VBoolean then Result := true;
vtChar : if Arg[0].VChar in [#0,#32] then Result := true;
vtExtended : if abs(Arg[0].VExtended^) < 0.000001 then Result := true;
vtString : if trim(Arg[0].VString^) = '' then Result := true;
vtPointer : if Arg[0].VPointer = nil then Result := true;
vtPchar : if trim(StrPas(Arg[0].VPchar)) = '' then Result := true;
else
MessageBeep(MB_ICONHAND);
if MessageDlg(' BAD PARAMETER' + CrLf + CrLf +
'Invalid Type Sent To FUNCTION EMPTY( [ Xvar ] )' + CrLf +
CrLf + ' INTEGER,BOOLEAN,CHAR,EXTENDED' + CrLf +
' STRING,POINTER or PCHAR Expected' + CrLf
,mtError,[mbAbort,mbIgnore],0) = 3 then
Application.Terminate;
end;
end;
// ==============================================================
// Same as Borland POS() except returns POS of LAST occurance
// ==============================================================
function RPos(SubStr : string; S : string) : integer;
var i : integer;
begin
SubStr := ReverseString(SubStr);
S := ReverseString(S);
i := pos(SubStr,S);
if i <> 0 then i := (length(S) + 1) - (i + length(SubStr) - 1);
Result := i;
end;
{ ================================================= }
{ Return Alpha Characters only from a passed string }
{ ================================================= }
function AlphaOnly(StrVar : string) : string;
var RetStr : string;
i : integer;
begin
RetStr := '';
for i := 1 to length(StrVar) do
if StrVar[i] in ['A'..'Z','a'..'z'] then RetStr := RetStr + StrVar[i];
Result := RetStr;
end;
{ =================================================== }
{ Return Numeric Characters only from a passed string }
{ =================================================== }
function NumericOnly(StrVar : string) : string;
var RetStr : string;
i : integer;
begin
RetStr := '';
for I := 1 to length(StrVar) do
if StrVar[i] in ['0'..'9'] then RetStr := RetStr + StrVar[i];
Result := RetStr;
end;
// =============================
// Return Windows Logon Name
// =============================
function GetLogonName(UCase : boolean = true) : string; platform;
var Count : DWORD;
begin
Count := 257;
SetLength(Result,Count);
{$WARNINGS OFF}
Win32Check(GetUserName(PChar(Result),Count));
SetLength(Result,StrLen(PChar(Result)));
{$WARNINGS ON}
if UCase then Result := UpperCase(Result);
end;
function GetDomainName(User : string = '') : string; platform;
var Count1,Count2 : DWORD;
Sd : PSecurityDescriptor;
Snu : SID_Name_Use;
begin
Sd := nil;
Snu := SIDTypeUser;
Count1 := 0;
Count2 := 0;
if trim(User) = '' then User := GetLogonName(false);
{$WARNINGS OFF}
LookupAccountName(nil,PChar(User),Sd,Count1,PChar(Result),Count2,Snu);
SetLength(Result,Count2 + 1);
Sd := AllocMem(Count1);
try
if LookupAccountName(nil,PChar(User),Sd,Count1,PChar(Result),Count2,Snu) then
SetLength(Result,StrLen(PChar(Result)))
else
Result := '';
finally
FreeMem(Sd);
end;
{$WARNINGS ON}
end;
// =====================================
// Get the serial number from hard disk
// =====================================
function GetDiskSerialNum(DriveLetter : char; HexValue : boolean = false) : string;
var VolumeSerialNumber : DWORD;
MaximumComponentLength : DWORD;
FileSystemFlags : DWORD;
Cmd : string;
begin
Cmd := '';
try
GetVolumeInformation(PChar(DriveLetter + ':\'),
nil, 0, @VolumeSerialNumber,
MaximumComponentLength, FileSystemFlags,
nil, 0);
if HexValue then
Cmd := IntToHex(HiWord(VolumeSerialNumber), 4) +
'-' + IntToHex(LoWord(VolumeSerialNumber), 4)
else
Cmd := IntToStr(VolumeSerialNumber);
except end;
Result := Cmd;
end;
// ========================
// Various Program Paths
// ========================
function GetExePath : string;
begin
Result := ExtractFilePath(Application.ExeName);
end;
function GetExeFile : string;
begin
Result := ExtractFileName(Application.ExeName);
end;
function GetExeName : string;
var ExName : string;
begin
ExName := ExtractFileName(Application.ExeName);
Result := copy(ExName,1,pos('.',ExName)-1);
end;
function GetAliasPath(Aname : string) : string;
var i : integer;
L : TStringList;
Cmd : string;
begin
Cmd := '';
L := TStringList.Create;
Session.GetAliasParams(Aname,L);
for i := 0 to L.Count-1 do
if uppercase(copy(L[i],1,5)) = 'PATH=' then
Cmd := copy(L[i],6,length(L[i])) + '\';
L.Free;
Result := Cmd;
end;
{ ================================================================= }
{ Extracts a field from a string delimited by "Delimeter" }
{ The source string is returned with the field and delim removed }
{ ================================================================= }
function ExtractField(var Source : string; Delimiter : string) : string;
var Cmd : string;
L,P : integer;
begin
P := pos(Delimiter,Source);
if P = 0 then begin
Cmd := Source;
Source := '';
end
else begin
Cmd := '';
L := length(Source);
Cmd := copy(Source,1,P - 1);
L := L - (length(Cmd) + 1);
Source := copy(Source,P + 1,L);
end;
Result := Cmd;
end;
// Similar - but sets a string list
function ExtractField(StrList : TStrings; const Source : string;
Delimiter : string) : string; overload;
var S : string;
begin
StrList.Clear;
S := Source;
while S <> '' do begin
StrList.Add(ExtractField(S,'|'));
end;
end;
// ============================================================
// Returns a string list of lines sepparated by delimiters
// Similar to BAAN string.scan
// eg. StringScan(Buffer,'|||%|',StrLst)
// =============================================================
procedure StringScan(const Buffer : string; const Mask : string;
LinesList : TStrings);
var i : integer;
MainLine : string;
begin
LinesList.Clear;
MainLine := Buffer;
for i := 1 to length(Mask) do LinesList.Add(ExtractField(MainLine,Mask[i]));
LinesList.Add(MainLine);
end;
// =============================================================
// Insert and delete into a string starting at position
// =============================================================
function StuffStr(const SrcStr,DestStr : string; Position : integer) : string;
var Cmd : string;
begin
Cmd := DestStr;
Delete(Cmd,Position,length(SrcStr));
Insert(SrcStr,Cmd,Position);
Result := Cmd;
end;
{ ================================================================= }
{ Extracts a field from a string comma delimited and }
{ enclosed with quotes "" }
{ ================================================================= }
function ExtractCommaDelim(var Source : string) : string;
var Cmd : string;
L,i : integer;
begin
Cmd := '';
i := 2;
L := length(Source);
if (trim(Source) <> '') and (Source[1] = '"') then begin // Quotes
while (Source[i] <> '"') and (i <= L) do inc(i);
if Source[i] = '"' then begin
Cmd := StripParen(copy(Source,1,i));
Delete(Source,1,i+1); // Remove Field and comma
end;
end
else
if (trim(Source) <> '') and (Source[1] <> '"') then begin // Integer
while (Source[i] <> ',') and (i <= L) do inc(i);
Cmd := copy(Source,1,i-1);
Delete(Source,1,i); // Remove Field and comma
end;
Result := Cmd;
end;
// ====================================================
// Return a unique filename in Default TEMP Directory
// File is Created and Closed 0 bytes in length
// ====================================================
function GetUniqueFileName : string;
var Cmd : string;
TempPath : string;
begin
SetLength(Cmd,257);
SetLength(TempPath,257);
GetTempPath(257,PChar(TempPath));
GetTempFileName(PChar(TempPath),'Mah',0,PChar(Cmd));
if pos(#0, Cmd) > 0 then Cmd := copy(Cmd, 1, pos(#0, Cmd) - 1);
Result := Cmd;
end;
// ===============================================
// Return a sortable date/time string of NOW
// in format YYYY/MM/DD-HH:NN:SS:ZZZ
// ===============================================
function DateStamp : string;
begin
Result := FormatDateTime('yyyy/mm/dd hh:nn:ss:zzz',Now);
end;
{ ======================================== }
{ This is a FAST swap routine that swaps }
{ the contents of any 2 variables. }
{ The variables may be of any type but }
{ the sizeof the VAR must be passed in Len }
{ the variable L. ASSEMBLER }
{ ======================================== }
procedure SwapMem(var Source,Dest; Len : integer);
begin
asm
push edi
push esi
mov esi,Source
mov edi,Dest
mov ecx,Len
cld
@1:
mov al,[edi]
xchg [esi],al
inc si
stosb
loop @1
pop esi
pop edi
end;
end;
// ======================================
// Return true if attached to a network
// ======================================
function IsNetworked : boolean;
begin
Result := (GetSystemMetrics(SM_NETWORK) and 1 = 1);
end;
// ======================================
// Various Error Message Dialog boxes
// Short cuts of MessageDlg()
// ======================================
procedure ErrorDlg(MessageStr : string; DoBeep : boolean = true);
begin
if DoBeep then MessageBeep(MB_ICONHAND);
MessageDlg(MessageStr,mtError,[mbOk],0);
end;
procedure InfoDlg(MessageStr : string; DoBeep : boolean = true);
begin
if DoBeep then MessageBeep(MB_ICONEXCLAMATION);
MessageDlg(MessageStr,mtInformation,[mbOk],0);
end;
function ConfirmDlg(MessageStr : string; DoBeep : boolean = true) : boolean;
begin
if DoBeep then MessageBeep(MB_ICONQUESTION);
Result := (MessageDlg(MessageStr,mtConfirmation,[mbYes,mbNo],0) = mrYes);
end;
procedure WarningDlg(MessageStr : string; DoBeep : boolean = true);
begin
if DoBeep then MessageBeep(MB_ICONASTERISK);
MessageDlg(MessageStr,mtWarning,[mbOk],0);
end;
// =================================================
// Set Maximum form size without covering task bar
// =================================================
procedure SetMaxSize(Form : TForm);
var h : THandle;
r : TRect;
begin
h := FindWindow('Shell_TrayWnd',nil);
if h <> 0 then begin
GetWindowRect(h,r);
if r.Bottom - r.Top <= 6 then
Form.SetBounds(0,0,Screen.Width,Screen.Height)
else
if r.Left > 0 then
Form.setBounds(0,0,r.Left,Screen.Height)
else
if r.Right < Screen.Width - 10 then
Form.SetBounds(r.Right,0,Screen.Width - r.Right,Screen.Height)
else
if r.Bottom < Screen.Height - 10 then
Form.SetBounds(0,r.Bottom,Screen.Width,Screen.Height - r.Bottom)
else
Form.SetBounds(0,0,Screen.Width,r.Top)
end
else
Form.SetBounds(0,0,Screen.Width,Screen.Height);
end;
// ====================================================
// Strip or add backslash to directory path
// See includetrailingbackslash()
// ====================================================
function CheckBackSlash(Path : string; MustHave : boolean = true) : string;
begin
Path := trim(Path);
if MustHave and (length(Path) > 0) and (Path[length(Path)] <> '\') then
Path := Path + '\';
if not MustHave and (length(Path) > 0) and (Path[length(Path)] = '\') then
delete(Path,length(Path),1);
Result := Path;
end;
// =====================================
// Graceful application termination
// Cannot use halt in OnShow of Form
// =====================================
procedure HaltApplication(UserMessage : string; ShowMessage : boolean = false);
begin
if ShowMessage then ErrorDlg(UserMessage);
Application.Terminate;
Raise EApplicationFail.Create(UserMessage);
end;
// ======================================================================
// Date functions to overcome Borland's standard StrTodate() and
// DateToStr(), which require and return dates in format DD/MM/YY
// These functions workd the same but require and return dates in
// with 4 digit year in format DD/MM/YYYY
// ======================================================================
function DateToStr4(TargetDate : TDateTime) : string;
var yyyy,mm,dd : word;
begin
DecodeDate(Targetdate,yyyy,mm,dd);
Result := FormatFloat('00',dd) + '/' +
FormatFloat('00',mm) + '/' +
FormatFloat('0000',yyyy);
end;
function StrToDate4(DateStr : string; ErrMessage : boolean = true) : TDateTime;
var yyyy,mm,dd : word;
Cmd : TDateTime;
begin
try
dd := StrToIntDef(copy(DateStr,1,2),0);
mm := StrToIntDef(copy(DateStr,4,2),0);
yyyy := StrToIntDef(copy(DateStr,7,4),0);
Cmd := EncodeDate(yyyy,mm,dd);
except
on E:Exception do begin
if ErrMessage then MessageDlg(E.Message,mtError,[mbOk],0);
Cmd := 0.0;
end;
end;
Result := Cmd;
end;
// ====================================
// Convert string to a TDateTime
// Format dd/mm/yyyy hh:nn:ss
// hh:nn:ss is optional
// ====================================
function StrToDateTime4(const DateTimeStr : string) : TDateTime;
var yyyy,mm,dd,hh,nn,ss : word;
S : string;
P : integer;
Cmd : TDateTime;
begin
Cmd := 0.0;
hh := 0;
nn := 0;
ss := 0;
if length(DateTimeStr) > 0 then begin
S := DateTimeStr;
P := pos('/',S);
dd := StrToIntDef(copy(S,1,P - 1),0);
S := copy(S,P + 1,18);
P := pos('/',S);
mm := StrToIntDef(copy(S,1,P - 1),0);
S := copy(S,P + 1,18);
P := pos(' ',S);
if P = 0 then
yyyy := StrToIntDef(S,0)
else begin
yyyy := StrToIntDef(copy(S,1,P - 1),0);
S := copy(S,P + 1,18);
P := pos(':',S);
if P = 0 then
hh := StrToIntDef(S,0)
else begin
hh := StrToIntDef(copy(S,1,P - 1),0);
S := copy(S,P + 1,18);
P := pos(':',S);
if P = 0 then
nn := StrToIntDef(S,0)
else begin
nn := StrToIntDef(copy(S,1,P - 1),0);
S := copy(S,P + 1,18);
ss := StrToIntDef(S,0);
end;
end;
end;
try
Cmd := EncodeDate(yyyy,mm,dd) + EncodeTime(hh,nn,ss,0);
except
on E: Exception do begin
MessageDlg(E.Message,mtError,[mbOk],0);
Cmd := 0.0;
end;
end;
end;
Result := Cmd;
end;
// Override and Warn if using standard Delphi functions
function DateToStr(TargetDate : TDateTime) : string;
begin
InfoDlg('Rather use DateToStr4()'#13'It is NOT dependant on ShortDateFormat'+
#13'and uses fixed format DD/MM/YYYY');
Result := '**/**/****';
end;
function StrToDate(DateStr : string) : TDateTime;
begin
InfoDlg('Rather use StrToDate4()'#13'It is NOT dependant on ShortDateFormat'+
#13'and uses fixed format DD/MM/YYYY');
Result := 0;
end;
function StrToDateTime(DateStr : string) : TDateTime;
begin
InfoDlg('Rather use StrToDateTime4()'#13'It is NOT dependant on ShortDateFormat'+
#13'and uses fixed format DD/MM/YYYY HH:NN:SS');
Result := 0;
end;
// ===========================================
// Check if a default printer is installed
// ===========================================
function IsDefaultPrinter(Showmessage : boolean = true) : boolean; overload;
var FDevice,FDriver,FPort : array [0..254] of char;
FHandle : THandle;
CurrentPrinterName : string;
Cmd : boolean;
begin
Cmd := false;
try
if Printer.Handle <> 0 then begin
Printer.GetPrinter(FDevice,FDriver,FPort,FHandle);
CurrentPrinterName := FDevice;
if CurrentPrinterName <> '' then
Cmd := true
else begin
Cmd := false;
if ShowMessage then ErrorDlg('No Default Printer is Defined');
end;
end;
except
if ShowMessage then ErrorDlg('Cannot Open Default Printer');
Cmd := false;
end;
Result := Cmd;
end;
function IsDefaultPrinter(out DefaultPrinterName : string;
Showmessage : boolean = true) : boolean; overload;
var FDevice,FDriver,FPort : array [0..254] of char;
FHandle : THandle;
CurrentPrinterName : string;
Cmd : boolean;
begin
Cmd := false;
try
if Printer.Handle <> 0 then begin
Printer.GetPrinter(FDevice,FDriver,FPort,FHandle);
CurrentPrinterName := FDevice;
DefaultPrinterName := CurrentPrinterName;
if CurrentPrinterName <> '' then
Cmd := true
else begin
Cmd := false;
if ShowMessage then ErrorDlg('No Default Printer is Defined');
end;
end;
except
if ShowMessage then ErrorDlg('Cannot Open Default Printer');
Cmd := false;
end;
Result := Cmd;
end;
// ============================
// Delay for X miliseconds
// 1000 ms = 1 second
// ============================
procedure Delay(ms : longword);
var TheTime : longword;
begin
TheTime := GetTickCount + ms;
while GetTickCount < TheTime do Application.ProcessMessages;
end;
// ===============================
// Convert Fontstyles to Integer
// ===============================
function FontStyleToInt(FS : TFontStyles) : integer;
var Cmd : integer;
begin
Cmd := 0;
if fsBold in FS then inc(Cmd);
if fsItalic in FS then inc(Cmd,2);
if fsUnderline in FS then inc(Cmd,4);
if fsStrikeOut in FS then inc(Cmd,8);
Result := Cmd;
end;
// ==========================================
// Is a font installed in the system ?
// ==========================================
function FontInstalled(const FontName : string) : boolean;
begin
Result := Screen.Fonts.IndexOf(FontName) > 0;
end;
// ===============================
// Convert Integer to TFontstyles
// ===============================
function IntToFontStyle(Num : integer) : TFontStyles;
var Cmd : TFontStyles;
begin
Cmd := [];
if (Num and 1) = 1 then Include(Cmd,fsBold);
if (Num and 2) = 2 then Include(Cmd,fsItalic);
if (Num and 4) = 4 then Include(Cmd,fsUnderline);
if (Num and 8) = 8 then Include(Cmd,fsStrikeout);
Result := Cmd;
end;
// ==========================================
// Get windows directorys
// ==========================================
(*
function WindowsDir : string;
var Dir : PChar;
WDir : string;
begin
GetMem(Dir,MAX_PATH);
GetWindowsDirectory(Dir,MAX_PATH);
WDir := string(Dir);
FreeMem(Dir);
if WDir[length(WDir)] <> '\' then WDir := WDir + '\';
Result := WDir;
end;
*)
function WindowsDir : string;
begin
SetLength(Result,255);
GetWindowsDirectory(PChar(Result),255);
SetLength(Result,StrLen(PChar(Result)));
end;
(*
function WindowsSystemDir : string;
var Dir : PChar;
WDir : string;
begin
GetMem(Dir,MAX_PATH);
GetSystemDirectory(Dir,MAX_PATH);
WDir := string(Dir);
FreeMem(Dir);
if WDir[length(WDir)] <> '\' then WDir := WDir + '\';
Result := WDir;
end;
*)
function WindowsSystemDir : string;
begin
SetLength(Result,255);
GetSystemDirectory(PChar(Result),255);
SetLength(Result,StrLen(PChar(Result)));
end;
function ComputerName : string; platform;
var Count : DWORD;
begin
Count := MAX_COMPUTERNAME_LENGTH + 1;
SetLength(Result,Count);
Win32Check(GetComputerName(PChar(Result),Count));
Setlength(Result,StrLen(PChar(Result)));
end;
// ================================================
// Load and Save TDBGrid Col settings from a file
// ================================================
procedure LoadGridSettings(FileName : string; Grid : TDBGrid; DefaultToExePath : boolean = true);
var FName : string;
begin
if DefaultToExePath then
FName := GetExePath + FileName
else
FName := FileName;
try
Grid.Columns.LoadFromFile(FileName);
except end;
end;
procedure SaveGridSettings(FileName : string; Grid : TDBGrid; DefaultToExePath : boolean = true);
var FName : string;
begin
if DefaultToExePath then
FName := GetExePath + FileName
else
FName := FileName;
try
Grid.Columns.SaveToFile(FileName);
except end;
end;
// ================================================================
// Return the three dates (Created,Modified,Accessed
// of a given filename. Returns FALSE if file cannot
// be found or permissions denied. Results are returned
// in TdateTime OUT parameters
// ================================================================
function GetFileTimes(FileName : string;
out Created : TDateTime;
out Modified : TDateTime;
out Accessed : TDateTime) : boolean;
var FileHandle : integer;
Cmd : boolean;
FTimeC,FTimeA,FTimeM : TFileTime;
LTime : TFileTime;
STime : TSystemTime;
begin
FileHandle := FileOpen(FileName,fmShareDenyNone);
Created := 0.0;
Modified := 0.0;
Accessed := 0.0;
if FileHandle < 0 then
Cmd := false
else begin
Cmd := true;
GetFileTime(FileHandle,@FTimeC,@FTimeA,@FTimeM);
FileClose(FileHandle);
// Created
FileTimeToLocalFileTime(FTimeC,LTime);
if FileTimeToSystemTime(LTime,STime) then begin
Created := EncodeDate(STime.wYear,STime.wMonth,STime.wDay);
Created := Created + EncodeTime(STime.wHour,STime.wMinute,STime.wSecond,STime.wMilliSeconds);
end;
// Accessed
FileTimeToLocalFileTime(FTimeA,LTime);
if FileTimeToSystemTime(LTime,STime) then begin
Accessed := EncodeDate(STime.wYear,STime.wMonth,STime.wDay);
Accessed := Accessed + EncodeTime(STime.wHour,STime.wMinute,STime.wSecond,STime.wMilliSeconds);
end;
// Modified
FileTimeToLocalFileTime(FTimeM,LTime);
if FileTimeToSystemTime(LTime,STime) then begin
Modified := EncodeDate(STime.wYear,STime.wMonth,STime.wDay);
Modified := Modified + EncodeTime(STime.wHour,STime.wMinute,STime.wSecond,STime.wMilliSeconds);
end;
end;
Result := Cmd;
end;
// =========================================
// Get IP address of current machine
//==========================================
function MyIPAddress : string;
type TaPInAddr = array [0..10] of PInAddr;
PaPInAddr = ^TaPInAddr;
var phe : PHostEnt;
pptr : PaPInAddr;
Buffer : array [0..63] of char;
Cmd : string;
I : integer;
GInitData : TWSADATA;
begin
WSAStartup($101, GInitData);
Cmd := '';
GetHostName(Buffer, SizeOf(Buffer));
phe := GetHostByName(buffer);
if (phe <> nil) then begin
pptr := PaPInAddr(Phe^.h_addr_list);
I := 0;
while pptr^[I] <> nil do begin
Cmd := StrPas(inet_ntoa(pptr^[I]^));
inc(I);
end;
WSACleanup;
end;
Result := Cmd;
end;
// ======================================
// Calculate the CPU speed in mhz
// ======================================
function CPUSpeed : integer;
const DELAYTIME = 500; // measure time in ms
var TimerHi,TimerLo: DWORD;
PriorityClass,Priority : integer;
begin
PriorityClass := GetPriorityClass(GetCurrentProcess);
Priority := GetThreadPriority(GetCurrentThread);
SetPriorityClass(GetCurrentProcess,REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_TIME_CRITICAL);
Sleep(10);
asm
dw 310Fh // rdtsc
mov TimerLo,eax
mov TimerHi,edx
end;
Sleep(DelayTime);
asm
dw 310Fh // rdtsc
sub eax,TimerLo
sbb edx,TimerHi
mov TimerLo,eax
mov TimerHi,edx
end;
SetThreadPriority(GetCurrentThread, Priority);
SetPriorityClass(GetCurrentProcess, PriorityClass);
Result := round(TimerLo / (1000.0 * DelayTime));
end;
// =================================================================
// Add/Delete currently running program to the AUTORUN
// section of the registry (W2000 should be OK)
// =================================================================
procedure SetAutoStart(AppTitleKey : string; Status : boolean = true);
const RUNKEY = '\Software\Microsoft\Windows\CurrentVersion\Run';
var WinReg : TRegistry;
begin
WinReg := TRegistry.Create;
try
WinReg.RootKey := HKEY_LOCAL_MACHINE;
if WinReg.OpenKey(RUNKEY,false) then begin
case Status of
false : WinReg.DeleteValue(AppTitleKey);
true : WinReg.WriteString(AppTitleKey,ParamStr(0));
end;
end;
finally
WinReg.Free;
end;
end;
// ========================================
// Remove the caption bar of a form.
// Normally called in OnCreate event
// ========================================
procedure RemoveFormCaption(Form : TForm);
begin
SetWindowLong(Form.Handle,GWL_STYLE,
GetWindowLong(Form.Handle,GWL_STYLE) AND NOT WS_CAPTION);
Form.ClientHeight := Form.Height;
Form.Refresh;
end;
// ===========================================
// Hex and Binary functions DELPHI forgot
// ===========================================
{ ===================================== }
{ Convert a HexString value to an Int64 }
{ Note : Last Char can be 'H' for Hex }
{ eg. '00123h' or '00123H' }
{ ===================================== }
function HexToInt(HexStr : string) : Int64;
var Cmd : Int64;
i : byte;
begin
HexStr := trim(HexStr);
if HexStr = '' then HexStr := '0';
HexStr := UpperCase(HexStr);
if HexStr[length(HexStr)] = 'H' then Delete(HexStr,length(HexStr),1);
Cmd := 0;
for i := 1 to length(HexStr) do begin
Cmd := Cmd shl 4;
if HexStr[i] in ['0'..'9'] then
Cmd := Cmd + (byte(HexStr[i]) - 48)
else
if HexStr[i] in ['A'..'F'] then
Cmd := Cmd + (byte(HexStr[i]) - 55)
else begin
Cmd := 0;
break;
end;
end;
Result := Cmd;
end;
{ ============================================== }
{ Convert an Int64 value to a binary string }
{ NumBits can be 64,32,16,8 to indicate the }
{ return value is to be Int64,DWord,Word }
{ or Byte respectively (default = 64) }
{ NumBits normally are only required for }
{ negative input values }
{ ============================================== }
function IntToBin(IValue : Int64; NumBits : word = 64) : string;
var Cmd : string;
begin
Cmd := '';
case NumBits of
32 : IValue := dword(IValue);
16 : IValue := word(IValue);
8 : IValue := byte(IValue);
end;
while IValue <> 0 do begin
Cmd := char(48 + (IValue and 1)) + Cmd;
IValue := IValue shr 1;
end;
if Cmd = '' then Cmd := '0';
Result := Cmd;
end;
{ ============================================== }
{ Convert a bit binary string to an Int64 value }
{ Note : Last Char can be 'B' for Binary }
{ eg. '001011b' or '001011B' }
{ ============================================== }
function BinToInt(BinStr : string) : Int64;
var i : byte;
Cmd : Int64;
begin
BinStr := trim(BinStr);
if BinStr = '' then BinStr := '0';
BinStr := UpperCase(BinStr);
if BinStr[length(BinStr)] = 'B' then Delete(BinStr,length(BinStr),1);
Cmd := 0;
for i := 1 to length(BinStr) do begin
if not (BinStr[i] in ['0','1']) then begin
Cmd := 0;
Break;
end;
Cmd := (Cmd shl 1) + (byte(BinStr[i]) and 1) ;
end;
Result := Cmd;
end;
// =======================================
// Generic integer to base conversions
// =======================================
const B36 : PChar = ('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ');
function IntToBase(Value : integer; Base : byte;
Digits : byte = 0): string;
var Cmd : string;
begin
Cmd := '';
repeat
Cmd := B36[Value mod Base] + Cmd;
Value := Value div Base;
until (Value div Base = 0);
Cmd := B36[Value mod Base] + Cmd;
while length(Cmd) < Digits do Cmd := '0' + Cmd;
Result := Cmd;
end;
function BaseToint(Value : string; Base : byte) : integer;
var i : byte;
Cmd : integer;
begin
Cmd := 0;
for i := 1 to length(Value) do begin
if (pos(Value[i],B36)-1) < Base then
Cmd := Cmd * Base + (pos(Value[i], B36)-1)
else begin
Cmd := 0;
break;
end;
end;
Result := Cmd;
end;
// ================================
// Sales functions
// ================================
{ ===================================== }
{ Discount a Value by PercentDiscount% }
{ 2 Overloaded versions }
{ One returns the actual disc amount }
{ ===================================== }
function Discount(Value : double; PercentDisc : double) : double; overload;
begin
Result := (Value * (100.0 - PercentDisc)) * 0.01;
end;
function Discount(Value : double; PercentDisc : double;
out DiscAmnt : double) : double; overload;
var Cmd : double;
begin
Cmd := (Value * (100.0 - PercentDisc)) * 0.01;
DiscAmnt := Value - Cmd;
Result := Cmd;
end;
{ ===================================== }
{ Markup a Value by PercentMarkup% }
{ 2 Overloaded versions }
{ One returns the actual markup amount }
{ ===================================== }
function MarkUp(Value : double; PercentMarkup : double) : double; overload;
begin
Result := Value * (1.0 + (PercentMarkup * 0.01));
end;
function MarkUp(Value : double; PercentMarkup : double;
out MarkupAmnt : double) : double; overload;
var Cmd : double;
begin
Cmd := Value * (1.0 + (PercentMarkup * 0.01));
MarkupAmnt := Value * (PercentMarkup * 0.01);
Result := Cmd;
end;
{ ==================================== }
{ Returns the GP% of a selling and }
{ cost price. }
{ ==================================== }
function GPpercent(Cost,Sell : double) : double; overload;
var Cmd : double;
begin
if Sell < 0.0001 then
Cmd := 0.0
else
Cmd := (1.0 - (Cost / Sell)) * 100.0;
Result := Cmd;
end;
function GPpercent(Cost,Sell : double;
out MarkupPercent : double) : double; overload;
var Cmd : double;
begin
MarkupPercent := 0;
if Sell < 0.0001 then
Cmd := 0.0
else begin
Cmd := (1.0 - (Cost / Sell)) * 100.0;
if Cost > 0.0001 then
MarkUpPercent := ((Sell - Cost) / Cost) * 100.0;
end;
Result := Cmd;
end;
// ========================================
// Return X,Y SCREEN coords of a control
// ========================================
procedure GetScreenXY(TargetControl : TControl; out X : integer;
out Y : integer);
var P : TPoint;
begin
P.x := TargetControl.Left;
P.y := TargetControl.Top;
P := TargetControl.Parent.ClientToScreen(P);
X := P.x;
Y := P.y;
end;
// ===============================================
// Convert a number to an English Sentence
// ===============================================
function NumToLetters(Number : extended; Currency : string = 'Rands';
Cents : string = 'Cents') : string;
const MaxAmt = 4294967295.99;
NumArr : array [1..19] of string[9] =
('One','Two','Three','Four','Five','Six','Seven',
'Eight','Nine','Ten','Eleven','Twelve',
'Thirteen','Fourteen','Fifteen','Sixteen',
'Seventeen','Eighteen','Nineteen');
TenArr : array [1..9] of string[7] =
('Ten','Twenty','Thirty','Forty','Fifty',
'Sixty','Seventy','Eighty','Ninety');
var Cmd : string;
Decimals : extended;
function RecurseNumber(N : longword) : string;
begin
case N of
1..19 : Result := NumArr[N];
20..99 : Result := TenArr[N div 10] +
' ' + RecurseNumber(N mod 10);
100..999 : Result := NumArr[N div 100] +
' Hundred ' +
RecurseNumber(N mod 100);
1000..999999 : Result := RecurseNumber(N div 1000) +
' Thousand ' +
RecurseNumber(N mod 1000);
1000000..999999999 : Result := RecurseNumber(N div 1000000) +
' Million ' +
RecurseNumber(N mod 1000000);
1000000000..4294967295 : Result := RecurseNumber(N div 1000000000) +
' Billion ' +
RecurseNumber(N mod 1000000000);
end;
end;
begin
Cmd := '';
if (Number < 0.00) or (Number > MaxAmt) then
MessageDlg('NumToLetters() - Number out of range',mtError,[mbOk],0)
else begin
Decimals := Frac(Number) * 100.9;
if (Number >= 1.00) then begin
Cmd := RecurseNumber(Round(Int(Number))) + ' ' + Currency;
Cmd := Cmd + ' + ' + FormatFloat('00',Decimals) + ' ' + Cents;
end
else
if Decimals > 0.00 then
Cmd := RecurseNumber(Round(Decimals)) + ' ' + Cents
else
Cmd := 'Zero ' + Currency + ' Zero ' + Cents;
end;
Result := Cmd;
end;
// =============================================
// Return a set describing char attributes
// =============================================
function CharTypeSet(Ch : char) : TCharTypesSet;
const
CHARS_ALPHA = ['a'..'z','A'..'Z'];
CHARS_UPPER = ['A'..'Z'];
CHARS_LOWER = ['a'..'z'];
CHARS_DIGIT = ['0'..'9'];
CHARS_HEX = ['0'..'9','A'..'F','a'..'f'];
CHARS_WHITE = [#9..#13,' '];
CHARS_PUNCT = ['!','"','''','(',')',',','.',';',':','?','[',']'];
CHARS_SIGN = ['+','-'];
CHARS_ANSI = [#0..#127];
CHARS_CONTROL = [#0..#31];
CHARS_OPERATOR = ['+','-','*','/','^'];
var Cmd : TCharTypesSet;
begin
Cmd := [];
if Ch in CHARS_ALPHA then Include(Cmd,chAlpha);
if Ch in CHARS_DIGIT then Include(Cmd,chDigit);
if Ch in CHARS_HEX then Include(Cmd,chHex);
if Ch in CHARS_UPPER then Include(Cmd,chUpper);
if Ch in CHARS_LOWER then Include(Cmd,chLower);
if Ch in CHARS_WHITE then Include(Cmd,chWhitespace);
if Ch in CHARS_PUNCT then Include(Cmd,chPunctuation);
if Ch in CHARS_SIGN then Include(Cmd,chSign);
if Ch in CHARS_ANSI then Include(Cmd,chAnsi);
if Ch in CHARS_CONTROL then Include(Cmd,chControl);
if Ch in CHARS_OPERATOR then Include(Cmd,chOperator);
Result := Cmd;
end;
// =============================================================================
// One line if .. then .. else statements
// like Clipper iif()
// =============================================================================
function iif(const Condition: Boolean; const TruePart, FalsePart: string): string; overload;
begin
if Condition then
Result := TruePart
else
Result := FalsePart;
end;
function iif(const Condition: Boolean; const TruePart, FalsePart: char): char; overload;
begin
if Condition then
Result := TruePart
else
Result := FalsePart;
end;
function iif(const Condition: Boolean; const TruePart, FalsePart: Byte): Byte; overload;
begin
if Condition then
Result := TruePart
else
Result := FalsePart;
end;
function iif(const Condition: Boolean; const TruePart, FalsePart: integer): integer; overload;
begin
if Condition then
Result := TruePart
else
Result := FalsePart;
end;
function iif(const Condition: Boolean; const TruePart, FalsePart: cardinal): cardinal; overload;
begin
if Condition then
Result := TruePart
else
Result := FalsePart;
end;
function iif(const Condition: Boolean; const TruePart, FalsePart: extended): extended; overload;
begin
if Condition then
Result := TruePart
else
Result := FalsePart;
end;
function iif(const Condition: Boolean; const TruePart, FalsePart: boolean): boolean; overload;
begin
if Condition then
Result := TruePart
else
Result := FalsePart;
end;
function iif(const Condition: Boolean; const TruePart, FalsePart: pointer): pointer; overload;
begin
if Condition then
Result := TruePart
else
Result := FalsePart;
end;
function iif(const Condition: Boolean; const TruePart, FalsePart: int64): int64; overload;
begin
if Condition then
Result := TruePart
else
Result := FalsePart;
end;
// =========================================================
// Return Handle to Desktop ListView
// eg. SendMessage(DeskTopLVhandle,LVM_ALIGN,LVA_ALIGNLEFT)
// =========================================================
function DeskTopLVhandle : THandle;
var S : string;
LVH : THandle;
begin
LVH := FindWindow('ProgMan',nil);
LVH := GetWindow(LVH,GW_CHILD);
LVH := GetWindow(LVH,GW_CHILD);
SetLength(S,40);
GetClassName(LVH,PChar(S),39);
if PChar(S) <> 'SysListView32' then LVH := 0;
Result := LVH;
end;
// ===========================================
// Load a stringlist with all window titles
// ===========================================
var XTS : TStrings;
procedure GetWindowsList(TS : TStrings);
function EnumWindowsCode(Wnd : hWnd; Form : TForm) : Boolean; Export; StdCall;
var Buffer : array[0..99] of char;
begin
GetWindowText(Wnd,Buffer,100);
if StrLen(Buffer) <> 0 then XTS.Add(StrPas(Buffer));
Result := true;
end;
begin
TS.Clear;
XTS := TS;
EnumWindows(@EnumWindowsCode,0);
end;
// ================================
// JAVA like toString functions
// ================================
function toString(Value : Variant): string;
begin
case TVarData(Value).VType of
varSmallInt,
varInteger : Result := IntToStr(Value);
varSingle,
varDouble,
varCurrency : Result := FloatToStr(Value);
varDate : Result := FormatDateTime('dd/mm/yyyy', Value);
varBoolean : if Value then Result := 'T' else Result := 'F';
varString : Result := Value;
else
Result := '';
end;
end;
// =============================================================================
// PosEx - Same as standard Pos function, except that you also
// can specify the start position, and ignore the case.
// =============================================================================
function PosEx(const SubStr,TargetS : string;
StartPos : integer = 1;
IgnoreCase : boolean = false) : integer;
var Cmd : integer;
begin
if StartPos < 1 then StartPos := 1;
if StartPos = 1 then begin
if IgnoreCase then
Cmd := Pos(UpperCase(SubStr),UpperCase(TargetS))
else
Cmd := Pos(SubStr,TargetS);
end
else begin
if IgnoreCase then
Cmd := Pos(UpperCase(SubStr),UpperCase(Copy(TargetS,StartPos,Length(TargetS))))
else
Cmd := Pos(SubStr,Copy(TargetS,StartPos,Length(TargetS)));
if Cmd > 0 then Cmd := Cmd + StartPos - 1;
end;
Result := Cmd;
end;
// =============================================================================
// PosCount - Same as standard Pos function, except that you also
// can specify the index occurance of the string;
// =============================================================================
function PosCount(const SubStr,TargetS : string; CountIndex : integer = 1) : integer;
var i,Cmd,P : integer;
begin
if CountIndex < 1 then CountIndex := 1;
Cmd := 0;
for i := 1 to CountIndex do begin
P := pos(SubStr,copy(TargetS,Cmd + 1,MAX_PATH));
if (P = 0) then begin
Cmd := 0;
break;
end
else
Cmd := Cmd + P;
end;
Result := Cmd;
end;
// ==========================================================
// Misc String functions
// ==========================================================
function IsNullStr(const StrVar : string) : boolean;
begin
Result := length(StrVar) = 0;
end;
function LastChar(StrVar : string) : char;
var Cmd : char;
begin
Cmd := #0;
if length(StrVar) > 0 then Cmd := StrVar[length(StrVar)];
Result := Cmd;
end;
procedure SetLastChar(var StrVar : string; CharValue : char);
begin
if length(StrVar) > 0 then StrVar[length(StrVar)] := CharValue;
end;
procedure SortStr(var StrVar : string);
var S : string;
procedure QuickSort(L, R: integer);
var I,J : integer;
c : char;
begin
repeat
I := L;
J := R;
c := S[(L + R) shr 1];
repeat
while S[I] < c do inc(I);
while S[J] > c do dec(J);
if I <= J then begin
SwapMem(S[I],S[J],1);
inc(I);
dec(J);
end;
until I > J;
if L < J then QuickSort(L,J);
L := I;
until I >= R;
end;
begin
S := StrVar;
if length(StrVar) > 1 then begin
QuickSort(1,length(StrVar));
StrVar := S;
end;
end;
procedure ReplaceChars(var StrVar : string; ThisChar,WithChar : char;
IgnoreCase : boolean = false);
var i : integer;
begin
for i := 1 to length(StrVar) do begin
if IgnoreCase then begin
if UpCase(StrVar[i]) = UpCase(ThisChar) then StrVar[i] := WithChar;
end
else
if StrVar[i] = ThisChar then StrVar[i] := WithChar;
end;
end;
procedure VarToStr(var Source; Count : integer; out StrVar : string;
ReplaceChar0With : char = #0);
var Cmd : string;
i : integer;
begin
SetLength(Cmd,Count);
FillChar(Cmd,0,SizeOf(Cmd));
move(Source,Cmd[1],Count);
for i := 1 to Count do if Cmd[i] = #0 then
Cmd[i] := ReplaceChar0With;
StrVar := Cmd;
end;
procedure StrToVar(const StrVar : string; out UtypedVar);
begin
try move(StrVar[1],UTypedVar,length(StrVar)); except end;
end;
function StartsWith(const SourceStr,TargetStr : string;
IgnoreCase : boolean = false) : boolean;
begin
if not IgnoreCase then
Result := (copy(TargetStr,1,length(SourceStr)) = SourceStr)
else
Result := (copy(UpperCase(TargetStr),1,length(SourceStr)) = UpperCase(SourceStr));
end;
function EndsWith(const SourceStr,TargetStr : string;
IgnoreCase : boolean = false) : boolean;
begin
if not IgnoreCase then
Result := (copy(TargetStr,length(TargetStr) - length(SourceStr) + 1,MAXINT) = SourceStr)
else
Result := (copy(UpperCase(TargetStr),length(TargetStr) - length(SourceStr) + 1,MAXINT) = UpperCase(SourceStr));
end;
// ==========================================
// Inc and Dec value with limit rollover
// ==========================================
procedure IncLimit(var X : longint; Limit : longint;
RollOverVal : longint = 0; IncBy : longint = 1);
var XVal : longint;
begin
XVal := X;
if XVal = Limit then
XVal := RollOverVal
else
inc(XVal,IncBy);
X := XVal;
end;
procedure DecLimit(var X : longint; Limit : longint;
RollUnderVal : longint = 0; DecBy : longint = -1);
var XVal : longint;
begin
XVal := X;
if XVal = Limit then
XVal := RollUnderVal
else
dec(XVal,DecBy);
X := XVal;
end;
// ==================================================
// Populate a string grid from an open query
// ==================================================
procedure QueryToStrGrid(Query : TQuery; StrGrid : TStringGrid; Titles : boolean = true);
var mCol,mLin,FntWidth : integer;
begin
FntWidth := StrGrid.Font.Size;
Query.First;
if not Query.Eof then begin
StrGrid.ColCount := Query.FieldCount;
StrGrid.RowCount := Query.RecordCount + iif(Titles,1,0);
StrGrid.FixedCols := 0;
StrGrid.FixedRows := iif(Titles,1,0);
if Titles then for mCol := 0 To Query.FieldCount - 1 do
StrGrid.Cells[mCol,0] := Query.Fields[mCol].FieldName;
mLin := 0;
while not Query.Eof do begin
for mCol := 0 To Query.FieldCount - 1 do begin
StrGrid.Cells[mCol,mLin + StrGrid.FixedRows] :=
Query.Fields[mCol].AsString;
StrGrid.ColWidths[mCol] := Query.Fields[mCol].DisplayWidth * FntWidth;
end;
Query.Next;
inc(mLin);
end;
end;
end;
// =============================================
// Copy String Grid to RTF Word Doc
// =============================================
procedure WriteToStream(var Stream : TStream; s : string);
begin
Stream.Write(PChar(s)^,Length(s));
end;
function Text2Rtf(s : string) : string;
var s2 : string;
i : integer;
begin
s2 := '';
i := 1;
while i <= length(s) do begin
case byte(s[i]) of
92 : s2 := s2 + '\\';
123 : s2 := s2 + '\{';
125 : s2 := s2 + '\}';
128..255 : s2 := s2 + '\''' + IntToHex(byte(s[i]),2);
else s2 := s2 +s [i];
end;//
inc(i);
end;
Result := s2;
end;
procedure StrGridToRTF(const Filename : string; SG : TStringGrid);
var St : TStream;
f,r,CellWidth,CellPos : integer;
begin
St := TFileStream.Create(Filename,fmCreate);
try
//RTF header
WriteToStream(St,'{\rtf1\ansi\deff0\deflang1033');
WriteToStream(St,'{\fonttbl{\f0\fnil\fcharset1{\*\fname Arial;}Arial;}}');
WriteToStream(St,'\viewscale100\uc1\pard\f0\fs20\par');
CellWidth := 2988;
//Writing Grid Data
for r := 0 to SG.RowCount-1 do begin
WriteToStream(St,'{\trowd\trgaph70\trleft0\trrh230');
CellPos := CellWidth;
for f := 0 to SG.ColCount-1 do begin
WriteToStream(St,'\clvertalt\clbrdrt\brdrs\brdrw10');
WriteToStream(St,'\clbrdrl\brdrs\brdrw10');
WriteToStream(St,'\clbrdrb\brdrs\brdrw10');
WriteToStream(St,'\clbrdrr\brdrs\brdrw10');
WriteToStream(St,'\cellx'+inttostr(cellpos));
CellPos := CellPos + CellWidth;
end;
for f := 0 to SG.ColCount-1 do
WriteToStream(St,'\pard\plain\fs20\intbl ' + Text2Rtf(SG.Cells[f,r])+'\cell ');
WriteToStream(St,'\row }');
end;
//End of RTF file
WriteToStream(St,'\par }');
finally
if Assigned(St) then St.Free;
end;
end;
procedure StrGridToHTML(const FileName : string; StrGrid : TStringGrid;
const Heading : string = '';
TextColor : TColor = clBlack;
TableBgColor : TColor = clAqua);
var Txt : TextFile;
i,ii : integer;
BgColor,TxColor : string;
begin
// Convert TColor to HTML Hex Color
BgColor := IntToHex(GetRValue(TableBgColor),2) +
IntToHex(GetGValue(TableBgColor),2) +
IntToHex(GetBValue(TableBgColor),2);
TxColor := IntToHex(GetRValue(TextColor),2) +
IntToHex(GetGValue(TextColor),2) +
IntToHex(GetBValue(TextColor),2);
// Create output file
AssignFile(Txt,FileName);
Rewrite(Txt);
// HTML Header Info
WriteLn(Txt,'<HTML>');
WriteLn(Txt,'<HEAD>');
WriteLn(Txt,'<TITLE>' + ExtractFileName(FileName) + '</TITLE>');
WriteLn(Txt,'</HEAD>');
WriteLn(Txt);
WriteLn(Txt,'<BODY TEXT=#' + TxColor + ' BGCOLOR=#CCCCCC>');
WriteLn(Txt,'<H1>' + Heading + '</H1>');
WriteLn(Txt,'<TABLE WIDTH=100% CELLPADDING=2 CELLSPACING=2 ' +
'BGCOLOR=#' + BgColor + ' BORDER=1>');
// Column Descriptions
WriteLn(Txt,' <TR>');
for i := 0 to StrGrid.ColCount - 1 do
WriteLn(Txt,' <TH>' + StrGrid.Cells[i,0] + '</TH>');
WriteLn(Txt,' </TR>');
// Write out the Grid Data
for i := 1 to StrGrid.RowCount - 1 do begin
WriteLn(Txt,' <TR>');
for ii := 0 to StrGrid.ColCount - 1 do
WriteLn(Txt,' <TD>' + StrGrid.Cells[ii,i] + '</TD>');
WriteLn(Txt,' </TR>');
end;
// Footer
WriteLn(Txt,'</TABLE>');
WriteLn(Txt,'<P>');
WriteLn(Txt,'<H3>' + IntToStr(StrGrid.ColCount) + ' Rows</H3>');
WriteLn(Txt,'</BODY>');
WriteLn(Txt,'</HTML>');
CloseFile(Txt);
end;
// ============================================
// Overwrite file with char 0 and delete
// recovery is impossible
// ============================================
procedure ShredFile(const FileName : string);
const BUFFSIZE = $FFFE;
var Fle : file;
Buffer : pointer;
FSize : integer;
begin
GetMem(Buffer,BUFFSIZE);
FillChar(Buffer^,BUFFSIZE,0);
AssignFile(Fle,FileName);
try
Reset(Fle,1);
FSize := FileSize(Fle);
while FSize > 0 do begin
BlockWrite(Fle,Buffer^,min(FSize,BUFFSIZE));
dec(FSize,BUFFSIZE);
end;
CloseFile(Fle);
DeleteFile(FileName);
except end;
FreeMem(Buffer);
end;
// ============================================================
// Returns -1, or 1 according to the sign of the argument
// Zero returns 1
// ============================================================
function Sign(Value : extended) : integer;
var Cmd : integer;
begin
if Value < 0.0 then Cmd := -1 else Cmd := 1;
Result := Cmd;
end;
// =======================================
// Better Rounder ie. 10's,100's etc
// =======================================
function RoundIt(Value : extended; Decimals : integer = 2) : extended;
var Nominator : extended;
begin
Nominator := Power(10,Decimals);
Result := Round(Value * Nominator) / Nominator;
end;
// ========================================================================
// This will copy a Paradox or dBase table from one directory to another.
// Note that this does not use BDE aliases. It would be possible to do that
// by declaring parameters for the source and destination databases,
// respectively.
// ========================================================================
function CopyPdxTable(SrcTable,DstTable : string; out ErrMess : string;
Overwrite : boolean = true) : boolean;
var DB : TDatabase;
STbl,DTbl : string;
Cmd : boolean;
begin
Cmd := false;
ErrMess := '';
if (ExtractFilePath(SrcTable) = '') then
STbl := ExtractFilePath(Application.EXEName) + SrcTable
else
STbl := SrcTable;
if (ExtractFilePath(DstTable) = '') then
DTbl := ExtractFilePath(Application.EXEName) + DstTable
else
DTbl := DstTable;
if FileExists(STbl) then begin
DB := TDatabase.Create(nil);
with DB do begin
Connected := False;
DatabaseName := ExtractFilePath(SrcTable);
DriverName := 'STANDARD';
Connected := True;
end;
try
Check(DBICopyTable(DB.Handle,Overwrite,PChar(STbl),nil,PChar(DTbl)));
Cmd := true;
except
on E: Exception do ErrMess := 'CopyPdxTable() - ' + E.Message;
end;
DB.Free;
end
else
ErrMess := 'CopyPdxTable() - Table does not Exist.';
Result := Cmd;
end;
// ===================================================
// Get INTEL chip features using CPUID call
// ===================================================
function GetCpuFeatures(FeatureList : TStrings = nil) : TCpuFeatures;
const
FPU_FLAG = $0001;
VME_FLAG = $0002;
DE_FLAG = $0004;
PSE_FLAG = $0008;
TSC_FLAG = $0010;
MSR_FLAG = $0020;
PAE_FLAG = $0040;
MCE_FLAG = $0080;
CX8_FLAG = $0100;
APIC_FLAG = $0200;
SEP_FLAG = $0800;
MTRR_FLAG = $1000;
PGE_FLAG = $2000;
MCA_FLAG = $4000;
CMOV_FLAG = $8000;
PAT_FLAG = $10000;
PSE36_FLAG = $20000;
PSNUM_FLAG = $40000;
MMX_FLAG = $800000;
FXSR_FLAG = $1000000;
SIMD_FLAG = $2000000;
var IsIntel : boolean;
VendorID : array [0..12] of char;
IntelID : array [0..12] of char;
FeaturesFlag,CpuSignature : DWord;
Temp : DWord;
Cmd : TCpuFeatures;
CpuType : byte;
// Local routine to add to List and Return SET
procedure CheckFeature(FeatureFlag : DWord;
const Item : string;
cpuFeatureType : TCpuFeature);
begin
if FeaturesFlag and FeatureFlag = FeatureFlag then begin
if FeatureList <> nil then FeatureList.Add(Item);
include(Cmd,cpuFeatureType);
end;
end;
begin
Cmd := [];
if FeatureList <> nil then FeatureList.Clear;
IsIntel := false;
IntelId := 'GenuineIntel'#0;
VendorID := '------------'#0;
try
asm
// Determine Intel CPUID support.
push ebx
push esi
push edi
mov eax,0 // Set up for CPUID instruction
db 00fh // CPUID - Get Vendor and check INTEL
db 0a2h
mov dword ptr VendorId,ebx
mov dword ptr VendorId[+4],edx
mov dword ptr VendorId[+8],ecx
cmp dword ptr IntelId,ebx // Check if it is INTEL
jne @@EndCPUID
cmp dword ptr IntelId[+4],edx
jne @@EndCPUID
cmp dword ptr IntelId[+8],ecx
jne @@EndCPUID // Not an Intel processor
mov byte ptr IsIntel,1 // Set IsIntel to true
cmp eax,1 // Ensure 1 is valid input for CPUID
jl @@EndCPUID // Else jump to end
mov eax,1
db 00fh // CPUID - Get features,family.model etc.
db 0a2h
mov CpuSignature,eax
mov FeaturesFlag,edx
shr eax,8 // Isolate family
and eax,0fh
mov byte ptr CpuType,al // Set cputype with family
@@EndCPUID :
pop edi // Restore registers
pop esi
pop ebx
end;
// Check Features Mask if Intel
if IsIntel then begin
if FeatureList <> nil then begin
FeatureList.Add('CPU Family ' + IntToStr(CpuType));
Temp := (CpuSignature shr 4) and $0f;
FeatureList.Add('CPU Model ' + IntToStr(Temp));
Temp := CpuSignature and $0f;
FeatureList.Add('CPU Stepping ' + IntToStr(Temp));
end;
CheckFeature(FPU_FLAG,'On-Chip FPU',cpuOnChipFPU);
CheckFeature(VME_FLAG,'VirtualMode Extensions',cpuVirtualModeExtensions);
CheckFeature(DE_FLAG,'Debugging Extensions',cpuDebuggingExtensions);
CheckFeature(PSE_FLAG,'Page Size Extensions',cpuPageSizeExtensions);
CheckFeature(TSC_FLAG,'Time Stamp Counter',cpuTimeStampCounter);
CheckFeature(MSR_FLAG,'Model Specific Registers',cpuModelSpecificRegisters);
CheckFeature(PAE_FLAG,'Physical Address Extensions',cpuPhysicalAddressExtensions);
CheckFeature(MCE_FLAG,'Machine Check Extensions',cpuMachineCheckExtensions);
CheckFeature(CX8_FLAG,'CMPXCHG8B Instruction',cpuCMPXCHG8B);
CheckFeature(APIC_FLAG,'On Chip APIC',cpuOnChipAPIC);
CheckFeature(SEP_FLAG,'Fast System Call',cpuFastSystemCall);
CheckFeature(MTRR_FLAG,'Memory Type Range Registers',cpuMemoryRangeRegisters);
CheckFeature(PGE_FLAG,'Page Global Enable',cpuPageGlobalEnable);
CheckFeature(MCA_FLAG,'Machine Check Architecture',cpuMachineCheckArchitecture);
CheckFeature(CMOV_FLAG,'Conditional Move Instruction',cpuConditionalMoveInstruction);
CheckFeature(PAT_FLAG,'Page Attribute Table',cpuPageAttributeTable);
CheckFeature(PSE36_FLAG,'32 Bit Page Size Extension',cpu32BitPageSzExtension);
CheckFeature(PSNUM_FLAG,'Processor Serial Number',cpuProcessorSerialNum);
CheckFeature(MMX_FLAG,'Intel MMX Technology',cpuMMXTechnology);
CheckFeature(FXSR_FLAG,'Fast Floating Point Save and Restore',cpuFastFloatingPoint);
CheckFeature(SIMD_FLAG,'Streaming SIMD Extensions',cpuSIMDExtensions);
end
else begin
if FeatureList <> nil then FeatureList.Add('Non-Intel or >486 Chip - Features Unknown');
include(Cmd,cpuNonIntel);
end;
except
if FeatureList <> nil then FeatureList.Add('No CPUID Support');
include(Cmd,cpuNoCPUID);
end;
Result := Cmd;
end;
// =======================================
// Get serial num - 486 non-Intel ?????
// =======================================
function GetCpuSerialNum : string;
var dw1,dw2,dw3 : DWORD;
begin
asm
push ebx
push esi
push edi
xor eax,eax
db 00fh // CPUID
db 0a2h
mov eax,1
db 00fh // CPUID
db 0a2h
mov dw3,eax
mov eax,3
db 00fh // CPUID
db 0a2h
mov dw2,edx
mov dw1,ecx
pop edi
pop esi
pop ebx
end;
Result := IntToHex(HiWord(dw3),4) + '-' +
IntToHex(LoWord(dw3),4) + '-' +
IntToHex(HiWord(dw2),4) + '-' +
IntToHex(LoWord(dw2),4) + '-' +
IntToHex(HiWord(dw1),4) + '-' +
IntToHex(LoWord(dw1),4);
end;
// ==============================================
// Get a list of computer names on network
// and return in string list
// ==============================================
procedure NetDomainList(StringList : TStrings);
const MAXENTRIES = 200;
type TBuffer = array [1..MAXENTRIES] of TNetResource;
PTBuffer = ^TBuffer;
var EHandle1,EHandle2 : THandle;
MaxItems1,MaxItems2,
BufLen : longword;
Buffer1,Buffer2 : PTBuffer;
Network : TNetResource;
i,ii : longword;
Loop1,Loop2 : longword;
begin
StringList.Clear;
GetMem(Buffer1,SizeOf(TBuffer));
GetMem(Buffer2,SizeOf(TBuffer));
FillChar(Network,SizeOf(Network),0);
Network.dwScope := RESOURCE_GLOBALNET;
Network.dwType := RESOURCETYPE_DISK;
Network.dwUsage := 0;
if WNetOpenEnum(RESOURCE_GLOBALNET,RESOURCETYPE_ANY,0,
@Network,EHandle1) = NO_ERROR then begin
repeat
MaxItems1 := MAXENTRIES;
BufLen := SizeOf(TBuffer);
Loop1 := WNetEnumResource(EHandle1,MaxItems1,Buffer1,BufLen);
if Loop1 = NO_ERROR then begin
// Process array of TNetResource
for i := 1 to MaxItems1 do begin
if WNetOpenEnum(RESOURCE_GLOBALNET,RESOURCETYPE_ANY,0,
@Buffer1^[i],EHandle2) = NO_ERROR then begin
repeat
MaxItems2 := MAXENTRIES;
BufLen := SizeOf(TBuffer);
Loop2 := WNetEnumResource(EHandle2,MaxItems2,Buffer2,BufLen);
if Loop2 = NO_ERROR then
for ii := 1 to MaxItems2 do StringList.Add(Buffer2^[ii].lpRemoteName);
until Loop2 = ERROR_NO_MORE_ITEMS;
WNetCloseEnum(EHandle2);
end;
end;
end;
until Loop1 = ERROR_NO_MORE_ITEMS;
FreeMem(Buffer1);
FreeMem(Buffer2);
WNetCloseEnum(EHandle1);
end;
end;
function GetParamVal(const TaggedParm : string;
IgnoreCase : boolean = true) : string;
var Cmd : string;
i,Len : integer;
Comp1,Comp2 : string;
begin
Cmd := '';
Comp1 := TaggedParm + '=';
if IgnoreCase then Comp1 := UpperCase(Comp1);
Len := length(Comp1);
for i := 1 to ParamCount do begin
Comp2 := copy(ParamStr(i),1,Len);
if IgnoreCase then Comp2 := UpperCase(Comp2);
if (Comp1 = Comp2) then begin
Cmd := trim(copy(ParamStr(i),Len + 1,length(ParamStr(i))));
break;
end;
end;
Result := UpperCase(Cmd);
end;
// ================================
// Return computer mac address
// ================================
function GetMACAddress: string;
var AdapterList : TLanaEnum;
NCB : TNCB;
function GetAdapterInfo(Lana : Char): String;
var Adapter : TAdapterStatus;
Cmd : string;
begin
FillChar(NCB,SizeOf(NCB),0);
NCB.ncb_command := Char(NCBRESET);
NCB.ncb_lana_num := Lana;
if Netbios(@NCB) <> Char(NRC_GOODRET) then
Cmd := 'mac not found'
else begin
FillChar(NCB,SizeOf(NCB),0);
NCB.ncb_command := Char(NCBASTAT);
NCB.ncb_lana_num := Lana;
NCB.ncb_callname := '*';
FillChar(Adapter,SizeOf(Adapter),0);
NCB.ncb_buffer := @Adapter;
NCB.ncb_length := SizeOf(Adapter);
NetBios(@NCB);
// Win 98 fails even tho card is there
// if Netbios(@NCB) <> Char(NRC_GOODRET) then begin
// Result := 'mac not found';
// Exit;
// end;
Cmd := IntToHex(Byte(Adapter.adapter_address[0]), 2) + '-' +
IntToHex(Byte(Adapter.adapter_address[1]), 2) + '-' +
IntToHex(Byte(Adapter.adapter_address[2]), 2) + '-' +
IntToHex(Byte(Adapter.adapter_address[3]), 2) + '-' +
IntToHex(Byte(Adapter.adapter_address[4]), 2) + '-' +
IntToHex(Byte(Adapter.adapter_address[5]), 2);
end;
Result := Cmd;
end;
begin
FillChar(NCB, SizeOf(NCB), 0);
NCB.ncb_command := Char(NCBENUM);
NCB.ncb_buffer := @AdapterList;
NCB.ncb_length := SizeOf(AdapterList);
Netbios(@NCB);
if Byte(AdapterList.length) > 0 then
Result := GetAdapterInfo(AdapterList.lana[0])
else
Result := 'mac not found';
end;
// =====================================================
// Allow for multi-line captions in win controls
// Call first and the set caption programatically
// =====================================================
procedure AllowMultiline(theControl : TWinControl);
var dwStyle : longint;
begin
dwStyle := GetWindowLong(theControl.handle, GWL_STYLE) or BS_MULTILINE;
SetWindowLong(theControl.Handle, GWL_STYLE, dwStyle);
end;
// ======================================================
// Get windows error as a text message
// Option show error dialog
// Option error number - default = 0 (GetLastError)
// ======================================================
function GetLastWinErr(ShowDialog : boolean = true;
ErrNum : integer = 0) : string;
var Cmd : string;
Err : integer;
begin
if ErrNum <> 0 then
Err := ErrNum
else
Err := GetLastError;
Cmd := SysErrorMessage(Err);
if ShowDialog then
MessageDlg('Windows Error ' + IntToStr(Err) + #13#10 + Cmd,
mtError,[mbOk],0);
Result := Cmd;
end;
// ================================================================
// Map network drive eg. NetMapDrive('G','\\pgbbxb1\col1\data');
// returns NO_ERROR or win error number . use GetLastWinErr
// ================================================================
function NetMapDrive(LocalDrive : char; const RemoteDrivePath : string;
UserName : string = ''; Password : string = '') : dword;
var NetResource : TNetResource;
LocalD : string;
PcUserName,PcPassword : PChar;
begin
PcUserName := nil;
PcPassword := nil;
LocalD := LocalDrive + ':';
NetResource.dwType := RESOURCETYPE_DISK;
NetResource.lpLocalName := PChar(LocalD);
NetResource.lpRemoteName := PChar(RemoteDrivepath);
NetResource.lpProvider := '';
if UserName <> '' then PcUserName := PChar(UserName);
if Password <> '' then PcPassword := PChar(Password);
Result := WNetAddConnection2(NetResource,PcPassword,PcUserName,CONNECT_UPDATE_PROFILE);
end;
function NetUnMapDrive(LocalDrive : char) : dword;
var LocalD : string;
begin
LocalD := UpCase(LocalDrive) + ':';
Result := WNetCancelConnection2(PChar(LocalD),CONNECT_UPDATE_PROFILE,true);
end;
// ==============================
// Null string = NOT MAPPED
// ==============================
function NetMappedName(LocalDrive : char) : string;
var BuffLen : DWORD;
LocalID : string;
begin
Result := ' ';
LocalID := LocalDrive + ':';
BuffLen := MAX_PATH;
SetLength(Result,BuffLen);
WNetGetConnection(PChar(LocalID),PChar(Result),BuffLen);
SetLength(Result,StrLen(PChar(Result)));
Result := trim(Result);
end;
// ==================================
// Exclude A and B drives
// '' = No Maps Available
// ==================================
function NetFindNextUnmapped : char;
var i : integer;
Drive : char;
DrivePath : string;
begin
Drive := #0;
for i := 3 to 26 do begin
DrivePath := char(i + 64) + ':';
if GetDriveType(PChar(DrivePath)) = 1 then begin
Drive := char(i + 64);
NetUnMapDrive(Drive);
break;
end;
end;
Result := Drive;
end;
// ===================================
// Get windows os/type
// ===================================
function GetOSName : string;
var osVerInfo : TOSVersionInfo;
majorVer, minorVer : integer;
OsCode : integer;
begin
OsVerInfo.dwOsVersionInfoSize := SizeOf(TOsVersionInfo);
if GetVersionEx(OsVerInfo) then begin
majorVer := OsVerInfo.dwMajorVersion;
minorVer := OsVerInfo.dwMinorVersion;
case (OsVerInfo.dwPlatformId) of
VER_PLATFORM_WIN32_NT : { Windows NT/2000 }
begin
if (majorVer <= 4) then
OsCode := cOsWinNT
else
if ((majorVer = 5) and (minorVer= 0)) then
OsCode := cOsWin2000
else
if ((majorVer = 5) and (minorVer = 1)) then
OsCode := cOsWhistler
else
OsCode := cOsUnknown;
end;
VER_PLATFORM_WIN32_WINDOWS : { Windows 9x/ME }
begin
if ((majorVer = 4) and (minorVer = 0)) then
OsCode := cOsWin95
else if ((majorVer = 4) and (minorVer = 10)) then begin
if (OsVerInfo.szCSDVersion[ 1 ] = 'A') then
OsCode := cOsWin98SE
else
OsCode := cOsWin98;
end else if (( majorVer = 4) and (minorVer = 90)) then
OsCode := cOsWinME
else
OsCode := cOsUnknown;
end;
else
OsCode := cOsUnknown;
end;
end else
OsCode := cOsUnknown;
if (OSCode = cOsUnknown) then
Result := '(Unkown O/S)'
else if (OSCode = cOsWin95) then
Result := 'Windows 95'
else if (OSCode = cOsWin98) then
Result := 'Windows 98'
else if (OSCode = cOsWin98SE) then
Result := 'Windows 98 2nd Edition'
else if ( OSCode = cOsWinME ) then
Result := 'Windows Millennium'
else if ( OSCode = cOsWinNT ) then
Result := 'Windows NT'
else if ( OSCode = cOsWin2000 ) Then
Result := 'Windows 2000 / NT 5'
else
Result := 'Microsoft Windows';
end;
// ===============================================
// Screen shot routines BMP and JPEG support
// ===============================================
procedure ScreenShotPrim(x : integer; y : integer;
Width : integer; Height : integer;
BMap : TBitMap);
var dc : HDC;
lpPal : PLOGPALETTE;
begin
if ((Width = 0) or (Height = 0)) then exit;
dc := GetDc(0);
if (dc = 0) then exit;
// do we have a palette device?
if (GetDeviceCaps(dc, RASTERCAPS) and RC_PALETTE = RC_PALETTE) then begin
GetMem(lpPal,SizeOf(TLOGPALETTE) + (255 * SizeOf(TPALETTEENTRY)));
FillChar(lpPal^,SizeOf(TLOGPALETTE) + (255 * sizeof(TPALETTEENTRY)),#0);
lpPal^.palVersion := $300;
lpPal^.palNumEntries := GetSystemPaletteEntries(dc, 0, 256, lpPal^.palPalEntry);
if (lpPal^.PalNumEntries <> 0) then BMap.Palette := CreatePalette(lpPal^);
FreeMem(lpPal,SizeOf(TLOGPALETTE) + (255 * sizeof(TPALETTEENTRY)));
end;
// copy from the screen to the bitmap
BitBlt(BMap.Canvas.Handle,0,0,Width,Height,Dc,x,y,SRCCOPY);
ReleaseDc(0,dc);
end;
procedure ScreenShot(X1,X2,Y1,Y2 : integer; BMap : TBitMap); overload;
begin
BMap.Width := X2 - X1;
BMap.Height := Y2 - Y1;
ScreenShotPrim(X1,Y1,BMap.Width,BMap.Height,BMap);
end;
procedure ScreenShot(BMap : TBitMap); overload;
begin
BMap.Width := Screen.Width;
BMap.Height := Screen.Height;
ScreenShotPrim(0,0,BMap.Width,BMap.Height,BMap);
end;
procedure ScreenShot(X1,X2,Y1,Y2 : integer; JMap : TJPEGImage); overload;
var BMap : TBitMap;
begin
BMap := TBitMap.Create;
BMap.Width := X2 - X1;
BMap.Height := Y2 - Y1;
ScreenShotPrim(X1,Y1,BMap.Width,BMap.Height,BMap);
JMap.Assign(BMap);
BMap.Free;
end;
procedure ScreenShot(JMap : TJPEGImage); overload;
var BMap : TBitMap;
begin
BMap := TBitMap.Create;
BMap.Width := Screen.Width;
BMap.Height := Screen.Height;
ScreenShotPrim(0,0,BMap.Width,BMap.Height,BMap);
JMap.Assign(BMap);
BMap.Free;
end;
// =========================
// Justify menu item
// =========================
procedure JustifyMenuItem(Menu : TMainMenu; MenuItem : TMenuItem;
Justify : TJustifyMenuMode = jsmRight);
var ItemInfo : TMenuItemInfo;
Buffer : array[0..80] of char;
begin
ItemInfo.cbSize := SizeOf(TMenuItemInfo);
ItemInfo.fMask := MIIM_TYPE;
ItemInfo.dwTypeData := Buffer;
ItemInfo.cch := SizeOf(Buffer);
GetMenuItemInfo(Menu.Handle,MenuItem.Command,false,ItemInfo);
case Justify of
jsmRight : ItemInfo.fType := ItemInfo.fType or MFT_RIGHTJUSTIFY;
jsmLeft : ItemInfo.fType := ItemInfo.fType and not MFT_RIGHTJUSTIFY;
jsmToggle : ItemInfo.fType := ItemInfo.fType xor MFT_RIGHTJUSTIFY;
end;
SetMenuItemInfo(Menu.Handle,MenuItem.Command,false,ItemInfo);
DrawMenuBar(Menu.WindowHandle);
end;
// ==========================================
// Create a tree menu into a TmenuItem
// ==========================================
const FEX = '.DOC.EXE.COM.HLP.INI.INF.TXT.BAT.DLL.SYS.VBX.OCX.VXD.FON.TTF.FOT';
procedure CreateTreeMenus(Path : string; Menu : TMainMenu;
Root : TMenuItem; ListImage : TImageList );
type pHIcon = ^HIcon;
var SR : TSearchRec;
Result : integer;
Item : TMenuItem;
SmallIcon : HIcon;
IconA : TIcon;
BitMapA : TBitMap;
Indice : integer;
IconOk : boolean;
procedure GetAssociatedIcon(FileName : TFilename;
pLargeIcon, PSmallIcon : pHIcon );
var IconIndex : word;
FileExt,FileType : string;
Reg : TRegistry;
p : integer;
p1,p2 : PChar;
begin
IconIndex := 0;
FileExt := UpperCase(ExtractFileExt(FileName));
if (((FileExt <> '.EXE' ) and (FileExt <> '.ICO')) or
(not(FileExists(FileName)))) then begin
Reg := NIL;
try
Reg := TRegistry.Create(KEY_QUERY_VALUE);
Reg.RootKey := HKEY_CLASSES_ROOT;
if (FileExt = '.EXE') then FileExt := '.COM';
if (Reg.OpenKeyReadOnly(FileExt)) then
try FileType := Reg.ReadString('');
finally Reg.CloseKey; end;
if ((FileType <> '' ) and
Reg.OpenKeyReadOnly(FileType + '\DefaultIcon')) then
try FileName := Reg.ReadString('');
finally Reg.CloseKey; end;
finally
Reg.Free;
end;
if (FileName <> '') then begin;
p1 := PChar(FileName);
p2 := StrRScan(p1,',');
if (p2 <> NIL) then begin
p := p2 - p1 + 1;
IconIndex := StrToInt(copy(FileName,p + 1,Length(FileName) - p ));
SetLength(FileName,p - 1);
end;
IconOk := (ExtractIconEx(PChar(FileName),IconIndex,PLargeIcon^,PSmallIcon^,1) <> 1);
end
else
IconOk := true;
end;
if IconOk then begin
try FileName := WindowsSystemDir + 'SHELL32.DLL';
except FileName := 'C:\WINDOWS\SYSTEM\SHELL32.DLL'; end;
case pos(FileExt,FEX) of
1 : IconIndex := 1;
5,9 : IconIndex := 2;
13 : IconIndex := 23;
17,21 : IconIndex := 63;
25 : IconIndex := 64;
29 : IconIndex := 65;
33,37,41,45,49 : IconIndex := 66;
53 : IconIndex := 67;
57 : IconIndex := 68;
61 : IconIndex := 69;
else
IconIndex := 0;
end;
if ((ExtractIconEx(PChar(FileName),IconIndex,PLargeIcon^,
PSmallIcon^,1) <> 1 )) then begin
if (PLargeIcon <> NIL) then PLargeIcon^ := 0;
if (PSmallIcon <> NIL) then PSmallIcon^ := 0;
end;
end;
end;
begin
Menu.Images := ListImage;
if (Path[Length(Path)] <> '\' ) then Path := Path + '\';
Result := FindFirst(Path + '*.*',faDirectory,SR);
while (Result = 0) do begin
if (((SR.Attr and faDirectory ) <> 0) and (SR.Name <> '.')
and (SR.Name <> '..')) then begin
Item := TMenuItem.Create(Menu);
Item.Caption := SR.Name;
Item.ImageIndex := 0;
Root.Add(Item);
CreateTreeMenus(Path + SR.Name,Menu,Item,ListImage);
end;
if (((SR.Attr and faAnyFile) <> 0) and (SR.Name <> '.')
and (SR.Name <> '..' )) then begin
Item := TMenuItem.Create(Menu);
Item.Caption := SR.Name;
GetAssociatedIcon(sr.Name,NIL,@SmallIcon);
IconA := TIcon.Create;
IconA.Handle := SmallIcon;
BitMapA := TBitMap.Create;
BitMapA.Width := IconA.Width;
BitMapA.Height := IconA.Height;
BitMapA.Canvas.Draw(0,0,IconA );
BitMapA.TransparentMode := tmAuto;
Indice := ListImage.Add(BitMapA,NIL);
Item.ImageIndex := Indice;
Root.Add(Item);
IconA.Free;
BitMapA.Free;
end;
Result := FindNext( SR );
end;
try FindClose( SR ); except end;
end;
// ================================================
// Bios Information 95/98 and 2000/NT compatible
// ================================================
function BiosDate : string;
var Cmd : string;
WinReg : TRegistry;
begin
WinReg := nil;
Cmd := '????????';
try
// Win 9x
SetString(Cmd,PChar(Ptr($FFFF5)),10);
except
// Win 2000/NT
try
WinReg := TRegistry.Create;
WinReg.RootKey := HKEY_LOCAL_MACHINE;
if WinReg.OpenKeyReadOnly('\HARDWARE\DESCRIPTION\System') then
Cmd := WinReg.ReadString('SystemBiosDate');
finally
WinReg.Free;
end;
end;
Result := Cmd;
end;
function BiosID : string;
var Cmd : string;
Buffer : PChar;
WinReg : TRegistry;
begin
WinReg := nil;
Cmd := '????????';
try
// Win 9x
SetString(Cmd,PChar(Ptr($F0000)),$2000);
except
// Win 2000/NT
try
WinReg := TRegistry.Create;
WinReg.RootKey := HKEY_LOCAL_MACHINE;
if WinReg.OpenKeyReadOnly('\HARDWARE\DESCRIPTION\System') then begin
GetMem(Buffer,$2000);
WinReg.ReadBinaryData('SystemBiosVersion',Buffer^,$2000);
Cmd := WinReg.ReadString('Identifier') + ' ' + Buffer;
FreeMem(Buffer);
end;
finally
WinReg.Free;
end;
end;
Result := Cmd;
end;
// ==============================
// Bit manipulation routines
// ==============================
const BitValArr : array [0..15] of word = (1,2,4,8,16,32,64,128,256,512,1024,
2048,4096,8192,16384,32768);
procedure SetBit(var WordValue : word; BitNum : word); overload;
begin
WordValue := WordValue or BitValArr[BitNum];
end;
procedure SetBit(var WordValue : word; BitNums : array of word); overload;
var BitVals,i : word;
begin
BitVals := 0;
for i := 0 to length(BitNums) - 1 do inc(BitVals,BitNums[i]);
WordValue := WordValue or BitVals;
end;
procedure ClearBit(var WordValue : word; BitNum : word); overload;
begin
WordValue := (WordValue or BitValArr[BitNum]) xor BitValArr[BitNum];
end;
procedure ClearBit(var WordValue : word; BitNums : array of word); overload;
var BitVals,i : word;
begin
BitVals := 0;
for i := 0 to length(BitNums) - 1 do inc(BitVals,BitNums[i]);
WordValue := (WordValue or BitVals) xor BitVals;
end;
procedure ToggleBit(var WordValue : word; BitNum : word); overload;
begin
WordValue := WordValue xor BitValArr[BitNum];
end;
procedure ToggleBit(var WordValue : word; BitNums : array of word); overload;
var BitVals,i : word;
begin
BitVals := 0;
for i := 0 to length(BitNums) - 1 do inc(BitVals,BitNums[i]);
WordValue := WordValue xor BitVals;
end;
function BitIsSet(WordValue : word; BitNum : word) : boolean; overload;
begin
Result := (WordValue and BitValArr[BitNum] = BitValArr[BitNum]);
end;
function BitIsSet(WordValue : word; BitNums : array of word) : boolean; overload;
var BitVals,i : word;
begin
BitVals := 0;
for i := 0 to length(BitNums) - 1 do inc(BitVals,BitNums[i]);
Result := (WordValue and BitVals = BitVals);
end;
function AndEqual(Value,AndValue : longword) : boolean;
begin
Result := (Value and AndValue) = AndValue;
end;
// ====================================
// TDataset Record copy routines
// ====================================
procedure CpyRecByName(Src,Dst : TDataSet);
var i : integer;
SField,DField : TField;
begin
for i :=0 to Src.FieldCount - 1 do begin
SField := Src.Fields[i];
DField := Dst.FindField(SField.FieldName);
if (DField <> nil) and
(DField.FieldKind = fkData) and not
DField.ReadOnly then begin
if (SField.DataType = ftString) or
(SField.DataType <> DField.DataType) then
DField.AsString := SField.AsString
else
DField.Assign(SField);
end;
end;
end;
procedure CpyRecByNum(Src,Dst : TDataSet);
var i : integer;
begin
for i :=0 to Src.FieldCount - 1 do begin
try
Dst.Fields[i].Value := Src.Fields[i].Value;
except
Dst.Fields[i].Assign(Src.Fields[i]);
end;
end;
end;
// ================================
// Recursive Search Tree for a file
// ================================
function SearchTree(StartDir,FileToFind : string;
out FileNamePath : string) : boolean; platform;
var Cmd : boolean;
// Recursive Dir Search
procedure SearchDir(DirPath : string);
var SearchRec : TSearchRec;
begin
DirPath := IncludeTrailingBackSlash(DirPath);
if FindFirst(DirPath + '*.*',faAnyFile,SearchRec) = 0 then begin
if Uppercase(SearchRec.Name) = FileToFind then begin
Cmd := true;
FileNamePath := DirPath + SearchRec.Name;
end
else begin
while not Cmd and (FindNext(SearchRec) = 0) do begin
if UpperCase(SearchRec.Name) = FileToFind then begin
Cmd := true;
FileNamePath := DirPath + SearchRec.Name;
end
else
if (SearchRec.Name <> '.') and
(SearchRec.Name <> '..') and
((SearchRec.Attr and faDirectory) = faDirectory) then
SearchDir(DirPath + SearchRec.Name);
end;
end;
FindClose(SearchRec);
end;
end;
// SearchTree
begin
Screen.Cursor := crHourGlass;
FileToFind := Uppercase(FileToFind);
FileNamePath := '';
Cmd := false;
SearchDir(StartDir);
Screen.Cursor := crDefault;
Result := Cmd;
end;
// ==================================================
// compares memory 0=equal -1=P1<P2 1=P1>P2
// ==================================================
function MemCompare(P1,P2 : pointer; Len : integer) : integer;
var Cmd,i : integer;
B1,B2 : ^byte;
begin
Cmd := 0;
B1 := P1;
B2 := P2;
for i := 0 to Len do begin
if B1^ < B2^ then begin
Cmd := -1;
break;
end;
if B1^ > B2^ then begin
Cmd := 1;
break;
end;
inc(B1);
inc(B2);
end;
Result := Cmd;
end;
// ===========================================
// Retieve Text from Win Calculator
// Useful ??? - but interesting
// ===========================================
var ObjHnd : THandle;
function WinCalcProc(ChildWnd : THandle; lParam : integer): bool; stdcall;
var Nme : array[0..127] of char;
begin
GetClassName(ChildWnd,Nme,SizeOf(Nme));
Result := (Nme <> 'Static');
if not Result then ObjHnd := ChildWnd;
end;
function WinCalcValue : string;
var WndCalc : THandle;
CalcStr : string;
Txt : array[0..127] of char;
begin
ObjHnd := 0;
CalcStr := 'No Calc Avail';
WndCalc := FindWindow('SciCalc',nil);
if WndCalc <> 0 then begin
EnumChildWindows(WndCalc,@WinCalcProc,0);
if (ObjHnd <> 0) then begin
GetWindowText(ObjHnd,Txt,SizeOf(Txt));
CalcStr := Txt;
end;
end;
Result := CalcStr;
end;
// ==========================================================
// Service Routines
// aMachine is UNC path or local machine if left empty
// ==========================================================
function ServiceStart(aMachine,aServiceName : string) : boolean;
var h_manager,h_svc: SC_Handle;
svc_status: TServiceStatus;
Temp: PChar;
dwCheckPoint: DWord;
begin
svc_status.dwCurrentState := 1;
h_manager := OpenSCManager(PChar(aMachine), nil,SC_MANAGER_CONNECT);
if h_manager > 0 then begin
h_svc := OpenService(h_manager, PChar(aServiceName),
SERVICE_START or SERVICE_QUERY_STATUS);
if h_svc > 0 then begin
temp := nil;
if (StartService(h_svc,0,temp)) then
if (QueryServiceStatus(h_svc,svc_status)) then begin
while (SERVICE_RUNNING <> svc_status.dwCurrentState) do begin
dwCheckPoint := svc_status.dwCheckPoint;
Sleep(svc_status.dwWaitHint);
if (not QueryServiceStatus(h_svc,svc_status)) then break;
if (svc_status.dwCheckPoint < dwCheckPoint) then begin
// QueryServiceStatus didn't increment dwCheckPoint
break;
end;
end;
end;
CloseServiceHandle(h_svc);
end;
CloseServiceHandle(h_manager);
end;
Result := (SERVICE_RUNNING = svc_status.dwCurrentState);
end;
function ServiceStop(aMachine,aServiceName : string) : boolean;
var h_manager,h_svc : SC_Handle;
svc_status : TServiceStatus;
dwCheckPoint : DWord;
begin
h_manager:=OpenSCManager(PChar(aMachine),nil,SC_MANAGER_CONNECT);
if h_manager > 0 then begin
h_svc := OpenService(h_manager,PChar(aServiceName),
SERVICE_STOP or SERVICE_QUERY_STATUS);
if h_svc > 0 then begin
if(ControlService(h_svc,SERVICE_CONTROL_STOP,svc_status)) then begin
if(QueryServiceStatus(h_svc,svc_status))then begin
while(SERVICE_STOPPED <> svc_status.dwCurrentState)do begin
dwCheckPoint := svc_status.dwCheckPoint;
Sleep(svc_status.dwWaitHint);
if(not QueryServiceStatus(h_svc,svc_status))then begin
// couldn't check status
break;
end;
if(svc_status.dwCheckPoint < dwCheckPoint)then break;
end;
end;
end;
CloseServiceHandle(h_svc);
end;
CloseServiceHandle(h_manager);
end;
Result := (SERVICE_STOPPED = svc_status.dwCurrentState);
end;
// ================================
// Status Constants
// SERVICE_STOPPED
// SERVICE_RUNNING
// SERVICE_PAUSED
// SERVICE_START_PENDING
// SERVICE_STOP_PENDING
// SERVICE_CONTINUE_PENDING
// SERVICE_PAUSE_PENDING
// =================================
function ServiceGetStatus(sMachine, sService: string ): DWord;
var h_manager,h_svc : SC_Handle;
service_status : TServiceStatus;
hStat : DWord;
begin
hStat := 0;
h_manager := OpenSCManager(PChar(sMachine) ,nil,SC_MANAGER_CONNECT);
if h_manager > 0 then begin
h_svc := OpenService(h_manager,PChar(sService),SERVICE_QUERY_STATUS);
if h_svc > 0 then begin
if(QueryServiceStatus(h_svc, service_status)) then
hStat := service_status.dwCurrentState;
CloseServiceHandle(h_svc);
end;
CloseServiceHandle(h_manager);
end;
Result := hStat;
end;
function ServiceGetStatusName(sMachine,sService: string ): string;
var Cmd : string;
Status : DWord;
begin
Status := ServiceGetStatus(sMachine,sService);
case Status of
SERVICE_STOPPED : Cmd := 'STOPPED';
SERVICE_RUNNING : Cmd := 'RUNNING';
SERVICE_PAUSED : Cmd := 'PAUSED';
SERVICE_START_PENDING : Cmd := 'STARTING';
SERVICE_STOP_PENDING : Cmd := 'STOPPING';
SERVICE_CONTINUE_PENDING : Cmd := 'RESUMING';
SERVICE_PAUSE_PENDING : Cmd := 'PAUSING';
else
Cmd := 'UNKNOWN STATE';
end;
Result := Cmd;
end;
// ===================================================
// Change Track Bar to emulate narrow W200 style
// ===================================================
procedure SetTrackbarNarrow(TB : TTrackBar);
var H : integer;
begin
H := GetWindowLong(TB.Handle,GWL_STYLE);
SetWindowLong(TB.Handle,GWL_STYLE,H xor $20);
end;
// =============================================================================
// Pop up the standard 'Browse for computer' dialog box
// Flags combination of
// BIF_BROWSEFORCOMPUTER Only computers else OK button is grayed.
// BIF_BROWSEFORPRINTER Only printers else OK button is grayed.
// BIF_DONTGOBELOWDOMAIN Don't include network folders below the domain level.
// BIF_RETURNFSANCESTORS Only file system ancestors else OK button is grayed.
// BIF_RETURNONLYFSDIRS Only file system dirs else OK button is grayed.
// ==================================================================
function BrowseFolder(const title : string;
Flags : longword = 0) : string;
var BrowseInfo : TBrowseInfo;
IDRoot : PItemIDList;
Path : array[0..MAX_PATH] of char;
begin
// Get the Item ID for Network Neighborhood
SHGetSpecialFolderLocation(0,CSIDL_NETWORK,IDRoot);
ZeroMemory(@BrowseInfo,SizeOf(TBrowseInfo));
ZeroMemory(@path,MAX_PATH);
BrowseInfo.hwndOwner := 0;
BrowseInfo.pidlRoot := IDRoot;
BrowseInfo.lpszTitle := PChar(title);
BrowseInfo.pszDisplayName := @path;
BrowseInfo.ulFlags := Flags;
// Show the browse dialog, get the Item ID for the selected item and convert it to a path
SHBrowseForFolder(BrowseInfo);
Result := path;
end;
// ==============================
// Execute browser at URL
// ==============================
procedure GoURL(const WebUrl : string);
begin
ShellExecute(Application.Handle,'open',PChar(WebUrl),nil,nil,SW_NORMAL);
end;
// =============================================================
// Change a checbox state without triggerring OnCheck Event
// =============================================================
procedure SetCheckBoxCheck(cb : TCheckBox; Checked : boolean);
begin
cb.Perform(BM_SETCHECK,byte(Checked),0);
end;
// ==================================================================
// Draw text at ANGLE rotation
// ==================================================================
procedure TextOutAngle(ParentCanvas : TCanvas;
X,Y : integer;
const FontName : string;
FontSize,Angle : integer;
const Txt : string;
Color : TColor = clBlack;
Transparent : boolean = true);
var lf : TLogFont;
tf : TFont;
begin
with ParentCanvas do begin
if Transparent then
SetBKMode(ParentCanvas.Handle,Windows.TRANSPARENT)
else
SetBKMode(ParentCanvas.Handle,Windows.OPAQUE);
Font.Name := FontName;
Font.Size := FontSize;
Font.Color := Color;
tf := TFont.Create;
tf.Assign(Font);
GetObject(tf.Handle, SizeOf(lf),@lf);
lf.lfEscapement := Angle * 10;
lf.lfOrientation := Angle * 10;
tf.Handle := CreateFontIndirect(lf);
Font.Assign(tf);
tf.Free;
TextOut(X,Y,Txt);
end;
end;
(* =============================================================================
AnimateShowWin() - Use in Form.FormCreate()
AnimateHideWin() - Use in Form.FormClose()
dwFlags can be:
AW_SLIDE Uses slide animation. By default, roll animation is used.
This flag is ignored when used with AW_CENTER.
AW_BLEND Uses a fade effect. This flag can be used only if hwnd
is a top-level window.
AW_CENTER Makes the window appear to collapse inward if AW_HIDE is used
or expand outward if the AW_HIDE is not used.
AW_HOR_POSITIVE Animates the window from left to right. This flag can be
used with roll or slide animation. It is ignored when
used with AW_CENTER or AW_BLEND.
AW_HOR_NEGATIVE Animates the window from right to left. This flag can be used
with roll or slide animation. It is ignored when used with
AW_CENTER or AW_BLEND.
AW_VER_POSITIVE Animates the window from top to bottom. This flag can be used
with roll or slide animation. It is ignored when used with
AW_CENTER or AW_BLEND.
AW_VER_NEGATIVE Animates the window from bottom to top. This flag can be used
with roll or slide animation. It is ignored when used with
AW_CENTER or AW_BLEND.
Following are used internally by AnimateWin()
AW_ACTIVATE Activates the window. Do not use this value with AW_HIDE.
AW_HIDE Hides the window. By default, the window is shown.
*)
procedure AnimateWin(Form : TForm; dwFlags : DWORD; dwTime : DWORD);
type
TAnimFunc = function(a : THandle; b,c : DWORD) : boolean; stdcall;
var Dll : integer;
AnimFunc : TAnimFunc;
begin
Dll := LoadLibrary('user32.dll');
if (Dll <> 0) then begin
AnimFunc := GetProcAddress(Dll,'AnimateWindow');
if (@AnimFunc <> nil) then AnimFunc(Form.Handle,dwTime,dwFlags);
Form.Invalidate;
FreeLibrary(Dll);
end;
end;
procedure AnimateShowWin(Form : TForm; dwFlags : DWORD; dwTime : DWORD = 300);
begin
AnimateWin(Form,dwFlags or AW_ACTIVATE,dwTime);
end;
procedure AnimateHideWin(Form : TForm; dwFlags : DWORD; dwTime : DWORD = 300);
begin
AnimateWin(Form,dwFlags or AW_HIDE,dwTime);
end;
// =============================================================================
// Print a string grid
// internal functions
// =============================================================================
procedure PrtStrGrid_SetColumnWidth(SG : TStringGrid; Cols : TList;
var Margins : TRect;
var Spacing : integer);
var i,k,w : integer;
begin
Printer.Canvas.Font.Style := [ fsBold ];
for i := 0 to pred(SG.ColCount) do
Cols.Add(Pointer(Printer.Canvas.TextWidth(SG.cells[i,0])));
Printer.Canvas.Font.Style := [];
for i := 1 to pred(SG.RowCount) do begin
for k := 0 to pred(SG.ColCount) do begin
w := Printer.Canvas.TextWidth(SG.Cells[k,i]);
if w > integer(Cols[k]) then Cols[k] := pointer(w);
end;
end;
w := 2 * Printer.Canvas.Font.PixelsPerInch div 3;
Margins := Rect(w,w,Printer.PageWidth - w,Printer.PageHeight - w);
Spacing := Printer.Canvas.Font.PixelsPerInch div 10;
w := 0;
for i := 0 to pred(Cols.Count) do
w := w + integer(Cols[i]) + Spacing;
w := w - Spacing;
if w > (Margins.Right - Margins.Left ) then begin
w := w - (Margins.Right - Margins.Left );
Cols[Cols.Count - 2] := pointer(integer(Cols[Cols.Count - 2]) - w);
end;
w := 0;
for i := 0 to pred(Cols.Count) do
w := w + integer(Cols[i]) + Spacing;
Margins.Right := w - Spacing + Margins.Left;
end;
procedure PrtStrGrid_DoLine(LineNo: integer;
SG : TStringGrid;
Cols : TList;
var Margins : TRect;
var Spacing : integer;
var y : integer);
var x,n,th : integer;
r : TRect;
begin
if length(SG.cells[1,LineNo]) <> 0 then begin
x := Margins.Left;
th := Printer.Canvas.TextHeight('�y');
for n := 0 to pred(Cols.Count) do begin
r := Rect(0,0,integer(Cols[n]),th);
OffsetRect(r,x,y);
Printer.Canvas.TextRect(r,x,y,SG.cells[n,lineno]);
x := r.Right + Spacing;
end; { for }
inc(y,th);
end;
end;
procedure PrtStrGrid_DoHeader(SG : TStringGrid;
Cols : TList;
var Margins : TRect;
var Spacing : integer;
var y : integer);
begin
y := Margins.Top;
Printer.Canvas.Font.Style := [fsBold];
PrtStrGrid_DoLine(0,SG,Cols,Margins,Spacing,y);
Printer.Canvas.Pen.Width := Printer.Canvas.Font.PixelsPerInch div 72;
Printer.Canvas.Pen.Color := clBlack;
Printer.Canvas.MoveTo(Margins.Left,y);
Printer.Canvas.Lineto(Margins.Right,y);
inc(y,2 * Printer.Canvas.Pen.Width);
Printer.Canvas.Font.Style := [ ];
end;
procedure PrtStrGrid_DoPrint(SG : TStringGrid;Cols : TList;
var Margins : TRect;
var Spacing : integer);
var i,y : integer;
begin
y:= 0;
for i := 1 to pred(SG.RowCount ) do begin
Application.ProcessMessages;
if y = 0 then PrtStrGrid_DoHeader(SG,Cols,Margins,Spacing,y);
PrtStrGrid_DoLine(i,SG,Cols,Margins,Spacing,y);
if y >= Margins.Bottom then begin
Printer.NewPage;
y := 0;
end;
end;
end;
// =============================================================================
// Print String Grid
// Public Library Call
// =============================================================================
procedure PrintStrGrid(StringGrid : TStringGrid; ShowSetupDialog : boolean = true);
var Margins : TRect;
Spacing : integer;
Cols : TList;
Setup : TPrinterSetupDialog;
CanPrint : boolean;
begin
Setup := nil;
CanPrint := true;
if ShowSetupDialog then begin
Setup := TPrinterSetupDialog.Create(nil);
CanPrint := Setup.Execute;
end;
if CanPrint then begin
Cols := TList.Create;
if Printer.Printing then printer.abort;
Printer.BeginDoc;
try
try
Printer.Canvas.Font.PixelsPerInch :=
GetDeviceCaps(Printer.Handle,logPixelsY);
Printer.Canvas.Font.Assign(StringGrid.font);
Printer.Canvas.Font.Color := clBlack;
Printer.Canvas.Pen.Color := clBlack;
PrtStrGrid_SetColumnWidth(StringGrid,Cols,Margins,Spacing);
Application.ProcessMessages;
PrtStrGrid_DoPrint(StringGrid,Cols,Margins,Spacing);
except
on E : Exception do ErrorDlg(E.Message);
end;
finally
if ShowSetupDialog then Setup.Free;
Cols.Free;
Printer.EndDoc;
end;
end;
end;
// ================================================================
// Check for BDE installed and Version
// ================================================================
function BDEinstalled(TerminateOnErr : boolean = false;
ShowErrorDlg : boolean = false;
InfoList : TStrings = nil) : string;
var RetVal : string;
BdeVer : SYSVersion;
M,D,H,N,S : word;
Y : smallint;
begin
RetVal := '';
try
Check(DbiGetSysVersion(BdeVer));
if (InfoList <> nil) then begin
InfoList.Clear;
InfoList.Add('ENGINE VERSION = ' + IntToStr(BdeVer.iVersion));
InfoList.Add('INTERFACE LEVEL = ' + IntToStr(BdeVer.iIntfLevel));
DbiDateDecode(BdeVer.DateVer,M,D,Y);
InfoList.Add('VERSION DATE = ' + FormatFloat('00',D) + '/' +
FormatFloat('00',M) + '/' +
FormatFloat('0000',Y));
DbiTimeDecode(BdeVer.TimeVer,H,N,S);
InfoList.Add('VERSION TIME = ' + FormatFloat('00',H) + ':' +
FormatFloat('00',N) + ':' +
FormatFloat('00',S div 1000));
end;
RetVal := IntToStr(BdeVer.iVersion);
except
RetVal := '';
if ShowErrorDlg then ErrorDlg('Borland Databse Engine (BDE)' + CrLf +
'is NOT Installed');
if TerminateOnErr then HaltApplication('');
end;
Result := RetVal;
end;
// ======================================
// Return Highest DAO installed
// ======================================
function GetDAOversion : integer; overload;
var Path : string;
Cmd,ThisVer : integer;
DirInfo : TSearchRec;
begin
Cmd := 0;
Path := ExtractFileDrive(WindowsDir) + '\Program Files\Common Files\' +
'Microsoft Shared\DAO\dao*.dll';
if FindFirst(Path,faAnyFile,DirInfo) = 0 then begin
ThisVer := StrToIntDef(copy(DirInfo.Name,4,3),0);
if ThisVer > Cmd then Cmd := ThisVer;
while FindNext(DirInfo) = 0 do begin
ThisVer := StrToIntDef(copy(DirInfo.Name,4,3),0);
if ThisVer > Cmd then Cmd := ThisVer;
end;
FindClose(DirInfo);
end;
Result := Cmd;
end;
function GetDAOversion(SList : TStrings) : integer; overload;
var Path : string;
Cmd,ThisVer : integer;
DirInfo : TSearchRec;
begin
SList.Clear;
Cmd := 0;
Path := ExtractFileDrive(WindowsDir) + '\Program Files\Common Files\' +
'Microsoft Shared\DAO\dao*.dll';
if FindFirst(Path,faAnyFile,DirInfo) = 0 then begin
ThisVer := StrToIntDef(copy(DirInfo.Name,4,3),0);
SList.Add(FormatFloat('0.00',ThisVer / 100.0));
if ThisVer > Cmd then Cmd := ThisVer;
while FindNext(DirInfo) = 0 do begin
ThisVer := StrToIntDef(copy(DirInfo.Name,4,3),0);
SList.Add(FormatFloat('0.00',ThisVer / 100.0));
if ThisVer > Cmd then Cmd := ThisVer;
end;
FindClose(DirInfo);
end;
Result := Cmd;
end;
// ========================================================
// Enable/Disable w2000 task manager from popping up
// ========================================================
procedure DisableTaskManager(const State : boolean);
var Reg : TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\System',
true) then
Reg.WriteInteger('DisableTaskMgr',integer(State));
finally
Reg.CloseKey;
Reg.Free;
end;
end;
// ========================================================
// Enable/Disable w2000 Lock Computer
// ========================================================
procedure DisableLockWorkStation(const State : boolean);
var Reg : TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\System',
true) then
Reg.WriteInteger('DisableLockWorkstation',integer(State));
finally
Reg.CloseKey;
Reg.Free;
end;
end;
// ========================================================
// Enable/Disable w2000 Change Password
// ========================================================
procedure DisableChangePassword(const State : boolean);
var Reg : TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\System',
true) then
Reg.WriteInteger('DisableChangePassword',integer(State));
finally
Reg.CloseKey;
Reg.Free;
end;
end;
// ========================================================
// Enable/Disable w2000 Logoff
// ========================================================
procedure DisableLogoff(const State : boolean);
var Reg : TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer',
true) then
Reg.WriteInteger('NoLogoff',integer(State));
finally
Reg.CloseKey;
Reg.Free;
end;
end;
// ========================================================
// Enable/Disable w2000 Shutdown
// ========================================================
procedure DisableShutDown(const State : boolean);
var Reg : TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer',
true) then
Reg.WriteInteger('NoClose',integer(State));
finally
Reg.CloseKey;
Reg.Free;
end;
end;
// ========================================================
// Enable/Disable w2000 Registry Tools
// ========================================================
procedure DisableRegistryTools(const State : boolean);
var Reg : TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\Policies\System',
true) then
Reg.WriteInteger('DisableRegistryTools',integer(State));
finally
Reg.CloseKey;
Reg.Free;
end;
end;
// ========================================================
// Enable/Disable w2000 Set Screen Saver Timeout
// ========================================================
procedure SetScreenSaverTimeOut(const TimeMilSec : integer);
var Reg : TRegistry;
begin
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_CURRENT_USER;
if Reg.OpenKey('\Software\Policies\Microsoft\Windows\Control Panel\Desktop',
true) then
Reg.WriteString('ScreenSaveTimeOut',IntToStr(TimeMilSec));
finally
Reg.CloseKey;
Reg.Free;
end;
end;
// ========================================================
// Enable/Disable w2000 Screen Saver
// ========================================================
procedure DisableScreenSaver(const State : boolean);
begin
if State = True then SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,0,nil,0);
if State = False then SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,1,nil,0);
end;
// =================================================================
// Set a string list to GUID desc + Separator + OLE Class name
// =================================================================
procedure LoadCLSID(StringList : TStrings; Separator : char = '*';
IncludeVersionIndependent : boolean = true);
const REGKEY = 'Software\Classes\CLSID';
var WinReg : TRegistry;
KeyNames,SubKeyNames : TStringList;
i : integer;
KeyDesc : string;
ProgID,VersID : boolean;
begin
StringList.Clear;
KeyNames := TStringList.Create;
SubKeyNames := TStringList.Create;
WinReg := TRegistry.Create;
WinReg.RootKey := HKEY_LOCAL_MACHINE;
if WinReg.OpenKey(REGKEY,false) then begin
WinReg.GetKeyNames(KeyNames);
WinReg.CloseKey;
// Traverse list of GUID numbers eg. {00000106-0000-0010-8000-00AA006D2EA4}
for i := 1 to KeyNames.Count - 1 do begin
if WinReg.OpenKey(REGKEY + '\' + KeyNames[i],false) then begin
// Set which keys are available
ProgID := WinReg.KeyExists('ProgID');
VersID := WinReg.KeyExists('VersionIndependentProgID');
// "ProgID" Key
if ProgID then begin
KeyDesc := WinReg.ReadString(''); // Read (Default) value
if trim(KeyDesc) = '' then KeyDesc := KeyNames[i];
WinReg.CloseKey;
if WinReg.OpenKey(REGKEY + '\' + KeyNames[i] +
'\ProgID',false) then begin
StringList.Add(KeyDesc + Separator + WinReg.ReadString(''));
WinReg.CloseKey;
// "Version Independent" Key if present and requested
if IncludeVersionIndependent and VersID then begin
KeyDesc := KeyDesc + ' [Version Independent]';
if WinReg.OpenKey(REGKEY + '\' + KeyNames[i] +
'\VersionIndependentProgID',false) then begin
StringList.Add(KeyDesc + Separator + WinReg.ReadString(''));
WinReg.CloseKey;
end;
end;
end;
end
else
WinReg.CloseKey;
end;
end;
end;
WinReg.Free;
SubKeyNames.Free;
KeyNames.Free;
end;
// ===========================================
// Delete a dir tree and all children
// ===========================================
function DeleteTree(const SrcPath : string) : boolean;
var FileOpStruct : TShFileOpStruct;
begin
FileOpStruct.Wnd := Application.Handle;
FileOpStruct.wFunc := FO_DELETE;
FileOpStruct.pFrom := PChar(SrcPath);
FileOpStruct.pTo := nil;
FileOpStruct.fFlags := FOF_NOCONFIRMATION or FOF_SILENT;
FileOpStruct.lpszProgressTitle := nil;
Result := (ShFileOperation(FileOpStruct) = 0);
end;
// ========================================================
// Functions to Darken,Lighten and mix colors by a percent
// ========================================================
function Darker(Color : TColor; Percent : integer) : TColor;
var R,G,B : byte;
begin
Percent := min(100,abs(Percent));
Color := ColorToRGB(Color);
R := GetRValue(Color);
G := GetGValue(Color);
B := GetBValue(Color);
R := R - MulDiv(R,Percent,100);
G := G - MulDiv(G,Percent,100);
B := B - MulDiv(B,Percent,100);
Result := RGB(R,G,B);
end;
function Lighter(Color : TColor; Percent : integer) : TColor;
var R,G,B : byte;
begin
Percent := min(100,abs(Percent));
Color := ColorToRGB(Color);
R := GetRValue(Color);
G := GetGValue(Color);
B := GetBValue(Color);
R := R + MulDiv(255 - R,Percent,100);
G := G + MulDiv(255 - G,Percent,100);
B := B + MulDiv(255 - B,Percent,100);
Result := RGB(R,G,B);
end;
function MixColors(C1,C2 : TColor) : TColor;
begin
Result := RGB((GetRValue(C1) + GetRValue(C2)) div 2,
(GetGValue(C1) + GetGValue(C2)) div 2,
(GetBValue(C1) + GetBValue(C2)) div 2);
end;
// =============================================
// Return a contrasting color to passed color
// =============================================
function ContrastColor(Color : TColor) : TColor;
var R,G,B : byte;
begin
Color := ColorToRGB(Color);
R := GetRValue(Color);
G := GetGValue(Color);
B := GetBValue(Color);
if R < 220 then R := 255 else R := 0;
if G < 220 then G := 255 else G := 0;
if B < 220 then B := 255 else B := 0;
Result := RGB(R,G,B);
end;
// =======================================
// Return Default Outlook Profile
// =======================================
function DefaultMessagingProfile : string;
var WinReg : TRegistry;
Cmd : string;
begin
Cmd := '';
WinReg := TRegistry.Create;
if WinReg.OpenKey('\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles',false)then begin
Cmd := WinReg.ReadString('DefaultProfile');
WinReg.CloseKey;
end;
WinReg.Free;
Result := Cmd;
end;
end.
Feliratkozás:
Bejegyzések (Atom)