Monthly Archives: March 2006

Leveraging breakpoint properties in the Delphi IDE

Quoted:

…if you set a breakpoint and right click on it (in the editor gutter) to display the context menu you can select “Breakpoint properties…”

Have you ever tried debugging GUI code where focus changes cause code to execute that you didn’t want executed? This is a fairly standard GUI debugging problem and one that Mark Edington (of Delphi R&D) recently discussed relating to debugging drag/drop code in the VCL. Having written a custom menuing system (in ActionBands) I’ve had my fair share of this type of debugging as well. I was helping Mark debug the above drag/drop problem and it occurred to me that it might be useful to mention a few breakpoint debugger features in our IDE that are likely overlooked by a lot of people.

For example, if you set a breakpoint and right click on it (in the editor gutter) to display the context menu you can select “Breakpoint properties…” (where you even aware of this menu item? 🙂 ) that displays a dialog with various properties controlling how the breakpoint will function. There are many useful properties on this dialog which I’m not going to discuss here and you can read about them in the online help however, the ones that I’d like to point out I think are particularly useful for GUI debugging situations:

  • The Pass count property allows you to set a value which represents the number of times execution passes this breakpoint before stopping.
  • If you click the “Advanced” button you can see a “Break” checkbox that indicates whether or not the debugger will actually break at this breakpoint. Now, you might be asking what good is a breakpoint that does not break? Well, it can be good for lots of things and one of which is outputing useful debugging information. Just below the Break checkbox is a Log Message dropdown which causes whatever you’ve typed to be sent to the Event Log whenever the breakpoint is hit. One advantage of this is you don’t have to litter your code with lots of OutputDebugString calls.
  • Another option is Eval Expression dropdown which will cause whatever expression you’ve entered to be evaluated where the results can also be viewed via the Event Log.

I realize for some people this is probably old news but perhaps there are at least a few people who can benefit.

User handle leak in TOleControl.CMDialogKey calling IOleControl.GetControlInfo

In versions of Delphi prior
to Delphi 2006 there is a bug in TOleControl.CMDialogKey which can cause a USER
handle leak when certain keys are pressed. The issue is that the method always
calls IOleControl.GetControlInfo(…)
which takes a CONTROLINFO
structure that has an hAccel member which is, according to MSDN, a:

Handle to an array of Windows ACCEL structures, each structure
describing a keyboard mnemonic. The array is allocated with the GlobalAlloc
function. The control always maintains the memory for this array; the caller of
IOleControl::GetControlInfo should not attempt to free the memory.

The problem with calling IOleControl.GetControlInfo is that each time it’s
called you get a new Windows USER handle allocated. In Delphi 2005, the problem
is apparent when the Welcome page is visible and you press the Enter key when
the focus is on some other window like the structure pane. This results in the
“loss” of a Windows USER handle with each keypress. In Delphi 2006, we’ve
addressed this by adding a TControlInfo data member to TOleControl and caching
the result from the first call to IOleControl.GetControlInfo in
TOleControl.CMDialogKey. So, for example if you’ve been using the TWebBrowser
control and are experiencing loss of Windows USER handles at an alarming rate
this could/should help explain why.

Update #1:

To be perfectly clear, this bug was fixed in
TOleControl in the RTM release of BDS 2006 which means subsequently the
TWebBrowser component no longer suffers from this problem.

Update #2:

Here is the code that was changed to correct
this problem:

Add the following data member to TOleControl:

  TOleControl = class(TWinControl, IUnknown, IOleClientSite,
IOleControlSite, IOleInPlaceSite, IOleInPlaceFrame, IDispatch,
IPropertyNotifySink, ISimpleFrameSite, IServiceProvider)
private
...
FControlInfo: TControlInfo; // Added new data member
...
end;

Change TOleControl.CreateControl by inserting the following two lines
(marked below):

procedure TOleControl.CreateControl;
var
Stream: IStream;
CS: IOleClientSite;
X: Integer;
begin
if FOleControl = nil then
try
try // work around ATL bug
...
OleCheck(FOleObject.QueryInterface(IOleControl, FOleControl));
FControlInfo.cb := SizeOf(FControlInfo); //*** Inserted ***
FOleControl.GetControlInfo(FControlInfo); //*** Inserted ***
OleCheck(FOleObject.QueryInterface(IDispatch, FControlDispatch));
...
except
DestroyControl;
raise;
end;
end;

Change the TOleControl.CMDialogKey method to read:

procedure TOleControl.CMDialogKey(var Message: TMessage);
var
Msg: TMsg;
Cmd: Word;
begin
if CanFocus then
begin
if (FControlInfo.cAccel <> 0) then
begin
FillChar(Msg, SizeOf(Msg), 0);
Msg.hwnd := Handle;
Msg.message := WM_KEYDOWN;
Msg.wParam := Message.WParam;
Msg.lParam := Message.LParam;
if IsAccelerator(FControlInfo.hAccel,
FControlInfo.cAccel, @Msg, Cmd) then
begin
FOleControl.OnMnemonic(@Msg);
Message.Result := 1;
Exit;
end;
end;
end;
inherited;
end;

That’s it. Now, when TOleControl.CMDialogKey is called it won’t try to
fetch the control info again and thus prevents the USER handle lleak.

An AJAX example in Delphi with ASP.NET using AJAX.NET Professional

Back in January, I wrote this
post
about using the magicAJAX.net framework in Delphi to illustrate AJAX from a Delphi ASP.NET application. This
month I’ve been looking at the AJAX.NET Professional framework
written by Michael Schwarz and
have converted his examples to Delphi for .NET using the 1.1 .NET framework
although AJAX.NET Pro supports both 1.1 and 2.0 versions of .NET.

Once again I’m going to assume you’ll be running this example from IIS. To
get this example to work in Delphi for .NET you’ll need to do the following:

  1. Grab the AJAX.NET Pro net download from here. All
    you’re really going to need is the AjaxPro.dll assembly.
  2. Download the Delphi example source code here
  3. Unzip delphi_ajaxpro.zip into \inetpub\wwwroot (it contains a directory
    called DelphiAJAXDemo)
  4. Create
    a virtual directory
    under IIS and point it at the directory created above
  5. Under \inetpub\wwwroot\DelphiAJAXDemo create a directory called “bin”
  6. Unzip AjaxPro.dll from the download in step 1 into the bin directory created
    above
  7. Start the IDE and open DelphiAJAXDemo.bdsproj
  8. From the Project Manager right click References and select Add Reference and
    add AjaxPro.dll
  9. Compile and run the project, you should see a page that looks like this

NOTE: I intentionally converted this example as closely to the C# example as
possible. I can’t say that in all cases I would have written the same code but I
felt the comparison between C# and Delphi was important enough to keep the code
as similar as possible.

Tags:

Update:

I found a bug in the Class demo code where some
data members were not being initialized. I’ve corrected the code and fixed the
download with these latest changes.

Update #2:

I missed the file quickguide.aspx which is
now included in the download.

Update #3: Fix blog tags for this entry

Update #4: This demo is now available online here.