Feeds:
Posts
Comments

help 64 Recently I had a very hard to find bug-problem with closing my application (made in Delphi).
It just refused to respond to Windows shutdown messages and prevented Windows to shutdown and restart..

I spent a lot of hours investigating this problem.
Initially the first part of the problem, because I was showing a dialog  for "Really close?" and preventing closing if some files are not saved, this was done in FormCloseQuery and it was stupid approach, because FormCloseQuery doesn’t know if windows is shutting down and thus preventing shutdown.

Than, I made a Message listeners for windows asking applications query for shutdown : WM_QueryEndSession and WM_EndSession.
The problem remained: the messages were received only second time. The first time when Windows was shutting down the application was still preventing shutdown, and only for the second Shutdown call, the messages were received and Application quit.
So something else was corrupting even the messages queue.

After some time, I accidentally came under another Form in same application, which also had FormCloseQuery, this time it was really needed because this Form was closing with fading effect and Query was preventing close until fader finished. So that was the second part of the problem.
Again I needed to listen for Shutdown messages in this Form.

So to conclude: you need to listen for Windows shut down Messages and Queries in every form that has FormCloseQuery or better yet avoid it, if you want to let windows shutdown normally. Also to note: Delphi made apps, on Windows shutdown exit instantly without freeing objects, so be careful and it is a good practice to listen to Shutdown procedure and to call your own Closing procedure manually.

More code examples on this soon..

 

Refresh Lately, I had a simple task to save and load some short strings in file.
The quickest and fastest way is to do it with streams (TFileStream or TMemoryStream).

Because in Delphi 2009 string type strings are Unicode so they are also double byte sized than in previous Delphi strings.
So you need to be very strict to write exact BYTES of the string, not characters, because character size is now 2 Bytes!

For Writing String to any stream use this Function :

The reading of string shoud be also exact with character size in mind. Because you can read only half of string:

 

function ReadStreamInt(Stream : TStream) : integer; 

begin 

   Stream.ReadBuffer(Result, SizeOf(Integer)); 

end; 

 

function ReadStreamStr(Stream : TStream) : string; 

  var 

   StrLen : integer; 

   TempStr : string; 

begin 

   TempStr := ''; 

   StrLen := ReadStreamInt(Stream); 

   if StrLen > -1 then 

      begin 

        SetLength(TempStr, StrLen); 

        //Here you should also check the character size 

        //Reading Bytes! 

        Stream.ReadBuffer(Pointer(TempStr)^, StrLen * SizeOf(Char)); 

        result := TempStr; 

     end 

     else Result := ''; 

end;

 

Then you can write functions for writing and loading strings for example:

 

function SaveToDFile( FileName: String; sDescr : string; ) : boolean;

   var  MemStr: TMemoryStream;

begin

    MemStr:= TMemoryStream.Create;

    try

     try

      WriteStreamStr( MemStr, sDescr );

      MemStr.SaveToFile(FileName);

      result := True;

     except

        on E:EWriteError do result := False;

     end;

   finally

      MemStr.Free;

   end;

end;

 

function LoadFromDFile( FileName: String; var sDescr : string; ) : boolean;

   var MemStr: TMemoryStream;

begin

   MemStr:= TMemoryStream.Create;

   try

    try

      MemStr.LoadFromFile(FileName);

      sDescr := ReadStreamStr( MemStr );

      result := True;

     except

       on E:EReadError do result := False;

     end;

    finally

     MemStr.Free;

    end;

end;

 

Hope it helps some.

book open sound 128  Microsoft introduced new TTS voice called "Anna" on Vista OS. Sadly it is only available for Vista and no separate download option for Windows XP users, personally I still use Windows XP on many machines. :(

You can find more info about TTS (Text To Speech engines on Microsoft site). New voice "Anna" is more clear and more natural, than any other voice available on XP versi0ns.

Still, there is an option to use "Anna" voice on XP for FREE. You need to download and install Microsoft Street And Trips 2009 !
It is available for FREE (60 day trial version is download-able from Microsoft here ). Its huge, about 1,5 GB, so you need some place on your hard disk for download.

So download and install Streets 2009. With it also Microsoft nice "Anna" TTS engine is installed to pronounce (speak) street names.
You can enjoy this product for 60 days, or uninstall it the same day — "Anna" engine will not be uninstalled ! Cool. :)
It is still left on system.
You can check its properties through Control Panel’s Speech category settings.

Enjoy!

PS. It is also possible to extract only TTS Anna setup files (About 32 MB). But still you should download Streets at first. Then after installation start, look for temp folder where temporary installation files were extracted. Most probably it will be your User’s "Documents and Settings/Local settings/Temp" Folder. Look for TTS.

view quick bar For those who are searching TCoolTrayIcon component written by Troels Jakobsen to support newest Delphi versions.

It’s a comprehensive component for adding icons to the traybar, allowing you to put a tray icon in your own programs. Can hide, show program button on Taskbar, show hide hint balloons and similar. The original component you can find on Troel’s website here: http://subsimple.com/delphi.asp

 

It’s freeware, so you can use it freely.

The problem is, it was updated very long ago, and supports Delphi versions until 6, though it should function ok till 2007 version.

As with Delphi 2009, where all string and char become full Unicode, version on Troel’s website isn’t compatible with Delphi 2009 anymore.

No problem. Sebastian Zierer already made some changes to support Unicode chars. You can find TCoolTrayIcon component for Delphi 2009 on his website : http://tib.s.songbeamer.eu/downloads/Cooltray.zip or you can download same copy here from my website: Download TCoolTrayIcon zip package

Update: 2008.11.12 fixes for Delphi 2009
Update: 2009.09.04 with Delphi 2010 package

For those who consider whether upgrade or buy Delphi 2009 I suggest to read these pages:

Some user opinions:

http://www.codegear.com/products/delphi/win32/quotes/

Some more views:

http://blogs.codegear.com/ao/2008/09/17/38947

In my personal opinion Delphi 2009 is worth buying, even for Unicode alone. At last.

If you want to show your custom popup menu in your TWebBrowser component I really recommend to you to download a EmbeddedWB component by bsalsa productions ( <http://www.bsalsa.com/product.html> ).
It is all the same TWebBowser only more user friendly, with more events and methods, added functionality.
By the way, it is all free.

With this EmbeddedWB you can easily make your own popup menu, even diffrent pop-ups for different selected items in web browser.

So for example, make a default popup when no selection exists, and one custom popup for selected text.

If you have EmbeddedWB installed and have one on your form, look for OnShowContextMenu event.

Then your custom popup can be shown with this example code:

function TForm.WebShowContextMenu(const dwID: Cardinal;

  const ppt: PPoint; const pcmdtReserved: IInterface;

  const pdispReserved: IDispatch): HRESULT;

begin

  //When we want to show our custum menu

  if (dwID = 4) //any text selection menu is about to show

    then begin

      TextPopup.Popup(ppt.X,ppt.Y);

    end

    else

      if Assigned(MyPopup) //if our popup is created

         then begin

           MyPopup.Popup(ppt.X, ppt.Y);

           Result := S_OK; //don't show WB popup

         end

         else Result := S_FALSE; //else show IE Popup

end;

 

IE has several different menus for images, text and so on. You can check what menu is about to show by

checking dwID:



CONTEXT_MENU_DEFAULT = 0;

CONTEXT_MENU_IMAGE = 1;

CONTEXT_MENU_CONTROL = 2;

CONTEXT_MENU_TABLE = 3;

CONTEXT_MENU_TEXTSELECT = 4;

CONTEXT_MENU_ANCHOR = 5;

CONTEXT_MENU_UNKNOWN = 6;

CONTEXT_MENU_IMGDYNSRC = 7;

CONTEXT_MENU_IMGART = 8;

CONTEXT_MENU_DEBUG = 9;

More info can be found here:

http://msdn2.microsoft.com/en-us/library/aa753264.aspx

http://www.bsalsa.com/ewb_on_show_context.html

Hope, this was helpful.

Some notes about Windows Desktop Search, well, for some people it may be a very good tool. I thought it should help me a lot to find my files. But wait, what a resource eater this WDS is, and really after 2 years of using it I didn’t become satisfactory with search results at all.
So I decided to uninstall it. Everything should be as always when you uninstall any MS program – simple, but really not for WDS.
I uninstalled it from “Add/Remove programs” control panel. OK, finished, restart. WDS doesn’t start and seems gone.

But later, when I pressed F3 in MyPC for file searching, and instead of standard simple windows search I SEE all again Windows Desktop Search, damn… Seems, it wasn’t full uninstall. Then I thought, I will install it again a fresh copy, and then I will uninstall. I downloaded an WDS EN 3.01 version from Microsoft website. Installed it. Going to remove in “Add/Remove Programs”, well…. it shows no WDS is installed (even with “Show updates” option). WTF. Though it clearly runs with my every computer start. So how to get rid of this thing without reinstalling all my pc??

Searching the google…
I found some information from Microsoft:

http://www.microsoft.com/technet/prodtechnol/windows/search/dtstshoot.mspx .

But man I didn’t install neither MSN search toolbars, nor other MS stuff, just WDS. Not useful information.
Found some instructions from Kotsar Andrew:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1456784&SiteID=1 .

OMG you need to create a WDS uninstall information manually, because I didn’t find such uninstall information even in my Windows dir (it should be hidden system folder with $KB….). :( (.
But then again I found a very good instructions here:

http://www.davidarno.org/2007/10/26/how-to-remove-windows-desktop-search/ .

Well seems I am not the only one here with WDS. Luckily I had another computer with WDS installed and uninstall information present there. So you need to copy that information to your Windows directory (for WDS 3.01 it should be $NtUninstallKB917013$, hidden system folder ) and manually run spuninst.exe. Then it should uninstall.

Refresh I’ll share some tip on File Creation in Delphi. Some day I had to make a solution to create same file stream a lot times in a cycle and to show it at regular intervals (it was opened in another application). Well, if file is already created and time interval get’s too short, you might get an exception, that file is "in use on another process" and even setting file permissions doesn’t help:

   1: var File : TFileStream 

   2: File := TFileStream.Create(OutputFile, fmCreate or fmShareExclusive)

The solution is, first to check out if file is in use. We could use Windows API CreateFile function for this task:

   1: function IsFileInUse(FileName: TFileName): Boolean;

   2:   var HFileRes: HFILE;

   3: begin

   4:   Result := False;

   5:   if not FileExists(FileName) then Exit;

   6:   HFileRes := CreateFile( PChar(FileName), //Windows API Create

   7:     GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING,

   8:     FILE_ATTRIBUTE_NORMAL, 0);

   9:   Result := (HFileRes = INVALID_HANDLE_VALUE);

  10:   //returns false File handle if file is in use

  11:   if not Result then CloseHandle(HFileRes); //Deny and close handle

  12: end;

Then you can check if file is in use:

   1: if NOT IsFileInUse(OutputFile)

   2:    then File := TFileStream.Create(OutputFile, fmCreate or  fmShareExclusive);

update: Zarko Gajis from About.com made another universal function for checking if "FileIsInUse" here:

Programmatically Check If File is In Use – Delphi Code