Tuesday, December 18, 2007

Format, String.Format and StringBuilder.AppendFormat

Format is Delphi's C-like format function. For example, Format('%s = %d',[MyString, MyInteger]).

String.Format and StringBuilder.AppendFormat are using FCL formatting. For example, String.Format('{0} = {1}', [MyString, MyInteger]).

Refer to http://msdn2.microsoft.com/en-us/library/hdekwk0b.aspx for further FCL Format information.

Monday, December 17, 2007

How to enable Glass Effect in Delphi 2007 for .Net (and Win32)

You will see the glass effect in Vista with Aero only. It appears to be a normal form if your OS does not support Aero.

Set the properties of the form as follow.



Then, write the following codes in OnCreate of the form.

And, tada.... here is the output.

Memory Leak and Real time memory (object) allocation monitoring

I like the way Delphi handles its object especially the ownership of the object. We tend to use MyComponent.Create(Owner) constructor to attach the object to an owner. Whenever the owner is disposed, the owner will dispose its children, in this case MyComponent. If MyComponent is not disposed, you might end up in a situation where your software is eating up memory every now and then. This is what we call memory leak. Delphi 2007 comes with an efficient memory manager to report memory leakage upon shut down by assigning ReportMemoryLeaksOnShutdown to True.

With Garbage Collector in .Net platform, all memory leak headache has been set aside and developers can now focus on implementing the business logic rather than trying to address the memory leak issue.

Let's go back to Win32 platform. Recently, I have developed a software for Fan Control System and my customer expects it to run 7x24 with minimum downtime. I guess memory leak is an issue here as I don't want my software to eat up memory over the time. So I have got the ReportMemoryLeaksOnShutdown set to True in my main form OnCreate event.
In addition, I let my software ran in a separate machine for a period of time with my Task Manager window on. From time to time, I took down the memory usage of my software (well, I was embarking the most primitive way) but I wasn't contented. I needed to know the true picture of memory/object allocation during the runtime. I searched the internet and found AQTime from AutomatedQA and downloaded the trial version. It worked perfectly and I was able to know the object allocation real time.

Is there a Garbage Collector for Delphi Win32? Read the article from Borland http://dn.codegear.com/article/28217 to find out more.

How to copy string content to unmanaged memory block in Delphi for .Net?

var
MyString: String;
UnManagedPtr: IntPtr;

begin
....
Marshal.Copy(MyString.ToCharArray, 0, UnManagedPtr, MyString.Length);
...
end;

Various copy methods are available for reference in M$DN
http://msdn2.microsoft.com/en-us/library/ms146626(VS.80).aspx

Sunday, December 16, 2007

Event Message Handling in Delphi 2007 for .Net

Type casting of LPARAM to TControl for CMMouseEnter... applicable to other Messages too.

SendMessage LPARAM type casting in Delphi 2007 for .Net

1. Declare an overload function of SendMessage instead of trying to typecast the LParam. The example below shows how to send TWinControl as LParam.
function SendMessage(hWnd: THandle; Msg: Cardinal; wParam: THandle; var LParam: TWincontrol): THandle; stdcall; overload; external 'User32.dll';

2. Using Marshal
Marshal.StructureToPtr(Control, LParam, True);
SendMessage(Control.Handle, CM_MOUSELEAVE, 0, THandle(LParam));



How to use unmanaged Win32 DLL in Delphi 2007 for .NET?

In this example, I will use GetCurrentThemeName in UxTheme.dll

Static/pre-binding:

function GetCurrentThemeName(pszThemeFileName: StringBuilder; cchMaxNameChars: Integer; pszColorBuff: StringBuilder; cchMaxColorChars: Integer; pszSizeBuff: StringBuilder; cchMaxSizeChars: Integer): HRESULT; stdcall; external 'UxTheme.dll';

Dynamic/post bidning:
This is a bit tricky.
  1. Add System.Runtime.InteropServices into uses clause.
  2. Add the function type and use [MarshalAs(UnmanagedType.LPWSTR)] for string parameter.
  3. Use Marshal.GetDelegateForFunctionPointer.
Confusing? Here is the example in Delphi 2007 for .Net

type
TGetCurrentThemeName = function(
[MarshalAs(UnmanagedType.LPWStr)]pszThemeFileName: string; cchMaxNameChars: Integer;
[MarshalAs(UnmanagedType.LPWStr)]pszColorBuff: string; cchMaxColorChars: Integer;
[MarshalAs(UnmanagedType.LPWStr)]pszSizeBuff: string; cchMaxSizeChars: Integer): HRESULT; stdcall;

var
H: THandle;
PAddr: IntPtr;
GetCurrentThemeName: TGetCurrentThemeName;
ThemeFilename, ColorBuff, SizeBuff: String;

begin
H := LoadLibrary('UxTheme.dll');

try

if H<>0 then
begin
PAddr := GetProcAddress(H, 'GetCurrentThemeName');
GetCurrentThemeName := TGetCurrentThemeName( Marshal.GetDelegateForFunctionPointer(PAddr, typeof(TGetCurrentThemeName)) );

SetLength(
ThemeFilename, 200);
SetLength(
ThemeFilename, 200);
SetLength(
SizeBuff, 200);

GCThemeName(
ThemeFilename, 200, ThemeFilename, 200, SizeBuff, 200);
end;

finally
FreeLibrary(H);
end;

end;

If you are looking for more Win32 API, here is a good site to visit http://www.pinvoke.net/default.aspx/uxtheme.GetCurrentThemeName

AllocateHWND and DeallocateHWND in Delphi 2007 for .NET

Add WinUtils or Borland.Vcl.WinUtils into uses clause and you will be able to use AllocateHWND and DeallocateHWND.

Where is HInstance in Delphi 2007 for .Net?

Add WinUtils or Borland.Vcl.WinUtils into uses clause and you will be able to use HInstance.