Posts Tagged ‘delphi’

SMLog suite v1.7

Tuesday, July 13th, 2010

Yesterday I changed the default error dialog in SMLog suite

Error dialog in SMLog v1.7

The format of log file now is text or XML (see the new Formatting property)

Also a few minor bugs fixed (list of all graphic adapters, computer name in Windows XP etc)

SMExport: Embedded images in html

Thursday, May 27th, 2010

Today I added the new feature for TSMExportToHTML component – the possibility to generate the html file with embedded images. Unfortunately the old IE (5/6) do not support this feature but FireFox, Opera, Safari will open the file without any problem

A few links:
http://www.sweeting.org/mark/blog/2005/07/12/base64-encoded-images-embedded-in-html
http://rifers.org/blogs/gbevin/2005/4/11/embedding_images_inside_html
Note: large images will not displayed due some limits in browser for encoded string

formating number

Wednesday, April 21st, 2010
function GetFormattedNumber(Value: Double): string; 
 
  function GetLastPos(const s: string): Integer; 
  begin 
    Result := Pos(DecimalSeparator, s)-1; 
    if (Result < 1) then 
      Result := Length(s) 
  end; 
 
var 
  i: Integer; 
begin 
  Result := FloatToStr(Value); 
  i := 3; 
  while (i < GetLastPos(Result)) do 
  begin 
    Insert(' ', Result, GetLastPos(Result)-i+1); 
    Inc(i, 4) 
  end; 
end;

Sample to use:

  lblTotal.Caption := GetFormattedNumber(123456.789);

Why I wrote this function? In Delphi I could use the FormatFloat(‘,###’, dbl) but FormatFloat uses the thousand separator which is defined in MS Windows (#160 by default). I need the space char always

TSMExportToJSON component

Friday, March 19th, 2010

In SMExport I added the new component to support the JavaScript Object Notation
The format of generated samples are available at http://www.json.org/example.html

For example:
{
“RECORD”: {
“Species No”: 90020
“Category”: “Fish”
“Common_Name”: “CommonFish 828″
“Species Name”: “Fish 275″
“Length (cm)”: 50
“Length_In”: 19,6850393700787
}
}

The dates encoded as the number of milliseconds since January 1st 1970. See the topic for this subject at
http://weblogs.asp.net/bleroy/archive/2008/01/18/dates-and-json.aspx

The binary values encoded in Base64 (same as in xml)

SMSchema: enable/disable some actions in designer

Thursday, March 18th, 2010

Added the new Actions property where developer have the control which options to enable/disable for end-user.

 For example, exclude the saEditRelation flag and user could not edit the options of relation/link.
 Or add the saDeleteItem flag to allow the delete the table/item in designer area

TSMExportAction type

Monday, March 15th, 2010

Created the new TAction for export support. Will be included in next SMExport

SMExport: data engines for cxTreeList/cxDBTreeList (Developer Express)

Sunday, February 21st, 2010

A few years ago Jens from OraTool.de wrote the dataengine component for cxGrid and I deployed this component as part of SMExport

But Developer Express also have the TcxTreeList and TcxDBTreeList components. In friday I wrote the dataengines for these components:

  •   TSMEcxTreeListDataEngine component: data engine for DevExpress TcxTreeList export
  •   TSMEcxDBTreeListDataEngine component: data engine for DevExpress TcxDBTreeList export

drag’n'drop from external applications

Monday, November 16th, 2009

In Friday in our SIM (Shareware Information System) I added the possibility to drag’n'drop the mail content from external mailer (MS Outlook, Outlook Express etc)

To add this feature you need:
1. declare two new Cliboard formats that need to be registered:

var
  CF_FILECONTENTS,
  CF_FILEDESCRIPTOR: Integer;initialization
 
  // Initialize the OLE libraries
  OleInitialize(nil);
 
  // Register the clipboard formats that we need to handle in the
  // OLE drag drop operation
  CF_FILECONTENTS := RegisterClipboardFormat(CFSTR_FILECONTENTS);
  CF_FILEDESCRIPTOR := RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
 
finalization
  OleUninitialize;

2. in OnCreate event for your form allow window to accept drop events. Just execute the next code:

OleCheck(RegisterDragDrop(Handle, Self));

3. for your form you need implement a few methods for IDropTarget interface:

type
  TfrmOrderWizard = class(TForm, IDropTarget)
  ...
  private
    { IDropTarget }
    function DragEnter(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint;
                       var dwEffect: Longint): HResult; stdcall;
    function DragOver(grfKeyState: Longint; pt: TPoint;
                      var dwEffect: Longint): HResult; stdcall;
    function DragLeave: HResult; stdcall;
    function Drop(const dataObj: IDataObject;
                  grfKeyState: Longint; pt: TPoint;
                  var dwEffect: Longint): HResult; stdcall;
    { IUnknown
     Ignore referance counting }
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
    ...

where:

function TfrmOrderWizard.DragEnter(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint;
     var dwEffect: Longint): HResult;
begin
  dwEffect := DROPEFFECT_COPY;
  Result  := S_OK;
end;
 
function TfrmOrderWizard.DragOver(grfKeyState: Longint; pt: TPoint;
     var dwEffect: Longint): HResult;
begin
  dwEffect := DROPEFFECT_COPY;
  Result := S_OK;
end;
 
function TfrmOrderWizard.DragLeave: HResult;
begin
  Result := S_OK;
end;
 
function TfrmOrderWizard._AddRef: Integer;
begin
   Result := 1;
end;
 
function TfrmOrderWizard._Release: Integer;
begin
  Result := 1;
end;
 
function TfrmOrderWizard.Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint;
  var dwEffect: Longint): HResult;
const
  PT_TSTRING = ULONG(30);
  PT_UNICODE = ULONG(31);
  PR_BODY    = PT_TSTRING or ($1000 shl 16);
  PR_BODY_W  = PT_UNICODE or ($1000 shl 16);
var
  aFmtEtc: TFORMATETC;
  aStgMed, stgmitem: TSTGMEDIUM;
  pData: PChar;
  pfgd: PFileGroupDescriptor;
  dwCount, dwfetch: Integer;
 
  stat: STATSTG;
  pstg: IStorage;
  pstm: IStream;
begin
  {Make certain the data rendering is available}
  if (dataObj = nil) then
    raise Exception.Create('IDataObject-Pointer is not valid!');
  with aFmtEtc do
  begin
    cfFormat := CF_TEXT;
    ptd := nil;
    dwAspect := DVASPECT_CONTENT;
    lindex := -1;
    tymed := TYMED_HGLOBAL;
  end;
  {Get the data}
  OleCheck(dataObj.GetData(aFmtEtc, aStgMed));
  try
    {Lock the global memory handle to get a pointer to the data}
    pData := GlobalLock(aStgMed.hGlobal);
    { Replace Text }
    MemoOrder.Text := pData;
  finally
    {Finished with the pointer}
    GlobalUnlock(aStgMed.hGlobal);
    {Free the memory}
    ReleaseStgMedium(aStgMed);
  end;
 
  // Get the file descriptors
  with aFmtEtc do
  begin
    cfFormat := CF_FILEDESCRIPTOR;
    ptd := nil;
    dwAspect := DVASPECT_CONTENT;
    lindex := -1;
    tymed := TYMED_HGLOBAL;
  end;
  OleCheck(dataObj.GetData(aFmtEtc, aStgMed));
  try
    pfgd := PFileGroupDescriptor(GlobalLock(aStgMed.hGlobal));
    // Iterate each of the files
    for dwCount := 0 to pfgd.cItems-1 do
    begin
      // Set up for getting the file data
      with aFmtEtc do
      begin
        cfFormat := CF_FILECONTENTS;
        ptd := nil;
        dwAspect := DVASPECT_CONTENT;
        lindex := dwCount;
        tymed := TYMED_ISTORAGE;
      end;
      if (dataObj.GetData(aFmtEtc, stgmitem) = S_OK) then
      begin
        // IStorage (handle the outlook item)
        pstg := IStorage(stgmitem.stg);
        // Hard coded to open the outlook message item stream
        if (pstg.OpenStream('__substg1.0_1000001F', nil, STGM_SHARE_EXCLUSIVE or STGM_READ, 0, pstm) = S_OK) or
           (pstg.OpenStream('__substg1.0_1000001E', nil, STGM_SHARE_EXCLUSIVE or STGM_READ, 0, pstm) = S_OK) then
        begin
          pstm.Stat(stat, STATFLAG_DEFAULT);
          pData := AllocMem(stat.cbSize);
          try
            pstm.Read(pData, stat.cbSize, @dwFetch);
            // Set the msg body
            MemoOrder.Lines.Add(String(pData));
          finally
            // Free buffer memory
            FreeMem(pData);
          end;
          // Free the stream
          pstm := nil;
        end;
        // Free the storage
        pstg := nil;
        // Release the storage medium
        ReleaseStgMedium(stgmitem);
      end;
    end;
  finally
    // Unlock the memory
    GlobalUnLock(aStgMed.hGlobal);
    // Release the storage medium
    ReleaseStgMedium(aStgMed);
  end;
 
  Result := S_OK;
end;

directives for Embacaderro Studio 2010 complier

Thursday, August 27th, 2009
{$IFDEF VER210}
  {$DEFINE SMForDelphi3}
  {$DEFINE SMForDelphi4}
  {$DEFINE SMForDelphi5}
  {$DEFINE SMForDelphi6}
  {$DEFINE SMForDelphi7}
  {$DEFINE SMForDelphi2005}
  {$DEFINE SMForDelphi2006}
  {$IFDEF BCB}
    {$DEFINE SMForBCB2006}
    {$DEFINE SMForBCB2007}
    {$DEFINE SMForBCB2009}
    {$DEFINE SMForBCB2010}
  {$ENDIF}
  {$DEFINE SMForDelphi2007}
  {$DEFINE SMForRADStudio2007}
  {$DEFINE SMForDelphi2009}
  {$DEFINE SMForDelphi2010}
{$ENDIF}

to check the password quality (strong or not strong)

Tuesday, July 21st, 2009

{returns an integer value (0 to 100) rating the key quality}
function PasswordQuality(const strPassword: string): Integer;
var
  i, j, intLen: Integer;
  QC: Double;
  boolUpper, boolLower: Boolean;
begin
  Result := 0;

  intLen := Length(strPassword);
  QC := 4*intLen;

  {at least 5 characters in password required}
  if (intLen > 4) then
  begin
    {check for repetitions (abcabc, aaaaa, 121212, etc}
    for i := 1 to (intLen div 2) do
    begin
      j := i+1;
      while (j <= intLen ) do
      begin
        if (Copy(strPassword, 1, i) = Copy(strPassword, j, i)) then exit;
        Inc(j, i);
      end
    end;

    {check the upper/lower cases}
    boolUpper := False;
    boolLower := False;
    for i := 1 to intLen do
    begin
      if (strPassword[i] in ['A'..'Z']) then
        boolUpper := True;
      if (strPassword[i] in ['a'..'z']) then
        boolLower := True;
    end;
    if boolUpper and boolLower then
      QC := 1.5*QC;

    {check the numbers}
    for i := 1 to intLen do
    begin
      if (strPassword[i] in ['0'..'9']) then
        if (boolUpper or boolLower) then
          QC := 1.5*QC;
    end;

    {check the signs}
    for i := 1 to intLen do
    begin
      if (strPassword[i] < ’0′) or (strPassword[i] > ‘z’) or
         ((strPassword[i] > ’9′) and (strPassword[i] < ‘A’)) then
        QC := 1.5*QC;
    end;

    if (QC > 100) then
      QC := 100;
    Result := Trunc(QC);
  end;
end;

Sample to use:
  i := PasswordQuality(edPassword.Text);
  lblPWQuality.Caption := IntToStr(i);
  if (i < 30) then
    lblPWQuality.Font.Color := clRed
  else
  if (i < 60) then
    lblPWQuality.Font.Color := clYellow
  else
    lblPWQuality.Font.Color := clWindowText;