Page 1 of 1

TToolTipManager

PostPosted: December 19th, 2012, 4:05 pm
by stewartbain
I like this component, does everything I want, but does not work with Delphi XE, Windows 7 and mdi. Non-mdi is perfect. Any suggestions?

Re: TToolTipManager

PostPosted: December 19th, 2012, 4:51 pm
by stewartbain
Additional info. It does work with mdi but only if compiling with "Use runtime themes" whereas non-mdi works without this setting.

Re: TToolTipManager

PostPosted: December 22nd, 2012, 10:11 am
by Kambiz
I'll check it out, but it may take a while.

Re: TToolTipManager

PostPosted: December 27th, 2012, 1:42 pm
by stewartbain
I have found the problem. The TToolInfo data structure needs to have its size set to 44 to work with MDI ( unless you compile with runtime themes ).

Re: TToolTipManager

PostPosted: January 2nd, 2013, 5:50 pm
by Ian Hinson
In Delphi7, CommCtrl.TToolTip resolves to this record type that already is 44 bytes in size:
tagTOOLINFOA = packed record
cbSize: UINT; // 4 bytes
uFlags: UINT; // 4 bytes
hwnd: HWND; // 4 bytes
uId: UINT; // 4 bytes
Rect: TRect; // 16 bytes
hInst: THandle; // 4 bytes
lpszText: PAnsiChar; // 4 bytes
lParam: LPARAM; // 4 bytes
end;
This record structure is correct for Common Controls 4.71.

But in Delphi 2010 and later, TToolTip includes a new additional field
lpReserved: pointer;
This makes the new record size 48 bytes big and corresponds to Common Controls 6.0
Since I only have D7 & D2010, it could've been introduced much earlier than D2010, but later than D7.

The increase in size of TOOLINFO is referred to in this Microsoft article.
http://msdn.microsoft.com/en-us/library ... 49(v=vs.85).aspx
The extra lpReserved field is often wrongly commented as being for "XP and later", but this is not strictly correct.
As the above article shows, the difference really relates to the comctl32.dll version, not the Windows version.
The lpReserved field is for Common Controls v6.0 and later.

When you add "themes" or XPMan to the uses block, the XP Manifest causes Common Controls 6.0 to be loaded.
You can test the ComCtl32 version at run-time using then ComCtrls.GetComCtlVersion() function.

I can confirm that the Delphi7 (44 byte) definition of TToolInfo is forward compatible.
That is, it works for both 4.71 and for 6.0, and in Windows 7 with apps compiled with Delphi 7.

But, the later (D2010>?) 48 byte structure (with the lpReserved field) is NOT backward compatible.
This problem is also referred to here:
http://www.codeproject.com/Articles/108 ... ip-control

The MDI/non-MDI thing you referred to led me to an interesting discovery.
Using my Delphi 2010 compiler I found (by calling GetComCtrlVersion at run-time) that standard non-MDI apps compiled in D2010 loaded up ComCtl32 v6.0 WHETHER OR NOT the XP Manifest component was added.
But D2010 MDI apps only load Common Controls v6.0 if the XPManifest component is added.

This explains why your MDI app had a problem. It was due to:
1) Delphi XE2 using the 48 byte structure that is not backward compatible to earlier Common Control versions, and
2) the fact that Delphi MDI apps revert loading to the earlier Common Controls at run-time under XE2 compiles.

So technically, the correct solution would be to:
1) Define both the 44 byte & 48 byte structures outside of the CommCtrl unit.
eg. TToolInfo (44 byte) and TToolInfoEx (48 byte)
2) for ToolTipManager to call ComCtrls.GetComCtrlVersion and pass the correct structure depending on whether the version is <6 or >=6.

But really, I doubt it would be worth the effort.
The problem only occurs if all of the following 3 conditions are met:
1) MDI app
2) written in a recent edition of Delphi, where
3) the developer decides to NOT use the XP Manifest.

Re: TToolTipManager

PostPosted: January 5th, 2013, 12:04 pm
by Kambiz
Thanks Ian for providing such a comprehensive information.

To keep backward compatibility, it was wise if the new structure was declared in Delphi CommCtrl unit under a new name. Missing this point is a bug of Delphi in my point of view.

@stewartbain: There are two places in the code that ToolInfo.cbSize is assigned. As Ian said, if you assign 44 to this field, tooltips will appear in all cases.

If I want to apply a fix in the code, I have to consider wide and ansi characters and also pay attention to 32bit and 64bit versions of Delphi. That's worthless, isn't it?