Tag: delphi

  • Parser for ePub files (e-book)

    Today I finished the component to parse the e-books in .epub format:

    http://en.wikipedia.org/wiki/Epub

    I added this parser in SMWord suite  Also I added this file format to Fast Document Viewer and ABA DocConvert

  • SMLog suite v1.7

    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

    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

    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

    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

    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

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

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

    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

    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

    {$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}