RAD Studio 2010 Review #6: VCL – Language enhancements for Touch and Gestures

RAD GesturesAs always keep in mind that we’re talking about a prerelease beta. Anything can change till release. Also, special greetings to Embarcadero for giving us the permission to talk about this.

Well, as you saw, the Gestures and Touch Engine is a very welcomed addition for some of you guys, rather uninteresting for the others. But because we’re a community, we must understand that sometimes the majority prevails. And for this, we must cast our opinion in order to give an accurate snapshot of our needs. That’s why your feedback is very appreciated. But please be constructive and not punitive. Anyway you were very good so far (kudos btw).

Saying this we’ll move now to the next step of our tour through RAD Studio’s internals. We’ll talk about another feature which was created to allow a smooth transition between different OSes giving the possibility to have the ‘same’ Pascal representation of an external interface for multiple operating systems even if this interface changes. The feature is called… 

delayed attribute

Remember that in the latest post I said that Delphi uses on WinXP it’s own recognition engine whereas on Windows 7 (yep, guys, RAD Studio is Windows 7 certified – thanks to Nick for letting us know) it uses the native Win7 Touch engine. How it is done?

In Windows.pas we see:

function CloseDesktop; external user32 name 'CloseDesktop';
function CloseTouchInputHandle; external user32 name 'CloseTouchInputHandle' delayed;
function CloseWindow; external user32 name 'CloseWindow';

By marking delayed a function or procedure allows the application to work on operating systems which doesn’t implement that specific function by not linking that function in the code from the beginning but at the call time.
In our concrete example above, the CloseTouchInputHandle is supported in Windows 7 only hence is delayed till is called.
By using a simple OS version check you can avoid that specific call – which will fail of course – on the systems which doesn’t support it. Something like:

if OSVersion=WINDOWS_7 then
  CloseTouchInputHandle
else
  MyInternalSimplerClose;

In my opinion this new attribute will be a nice addition to everyone who has to support external libraries which evolve in time, especially for the ones who need to translate / write headers.

Do you think that this will be really useful?

26 thoughts on “RAD Studio 2010 Review #6: VCL – Language enhancements for Touch and Gestures

  1. It would be a good idea to avoid the OS version check and instead handle the error from the call in an efficient way.

    Something like:

    if CallExist( CloseTouchInputHandle ) then
    begin
    // something
    CloseInputHandle( );
    // something
    end
    else
    // Generic code

    Where CallExists ís a “magic” function that caches the result from the first load check internally.

    • Hear, hear! If the entry point is there, the function is available. It’s silly (and error-prone) to force us to duplicate that knowledge in a manual version check.

    • I like the way C++Builder handles delay loading of DLL functions. There are several hooks made available, so for instance, if a function cannot be found in a DLL, or even if the DLL cannot be loaded into memory, the application code has a chance to provide an alternative DLL handle and/or a pointer to an alternative function, even one implemented in the app’s local code. No OS checking needed, and it makes the app code much more seemless as it can just call the intended DLL function unconditionally and let the hooks handle any necessary hookup issues behind the scenes. It would have made more sense for CodeGear to port that logic into Delphi rather than come up with a whole new loading system.

  2. The feature looks really nice! Unlike your example version check code, which is pretty crappy 😉 Better would be to do

    if CheckWin32Version(6, 1) then //CheckWin32Version is in SysUtils.pas
    CloseTouchInputHandle
    else
    MyInternalSimplerClose;

    Ironically enough, that Windows 7 is ‘really’ Windows 6.1 is partly due to MS not wanting to break buggy version checking code…

  3. Even easier would be:

    in the initialization:

    if OSVersion=WINDOWS_7 then
    CloseTouchInputHandle := GetProcAddress(…);
    else
    CloseTouchInputHandle := @MyInternalSimplerClose;

    And after that just call CloseInTouchInputHandle, no matter on which OS you are running.

  4. I am unconvinced that touch is going to be any more popular than sideshow. That said, I see the devteam felt they needed to support it.

    Gestures will probably get used by a lot of programmers, so still I see why that is included (even if it falls well outside the trainability curve for most users).

    The delayed semantic is interesting, but since you have to do a lot of the work yourself anyways, I’m not sure it does anything but cloud the issue and give you a chance to forget things. It might almost be better off if you left it out.

    Perhaps if it at least also included a function reference like the stored directive for properties, maybe a second call for a replacement stub when it is not there at all.

    We’ll leave “Delayed” in the likely to cause more problems for everyone than it is worth column for now and wait to see how it plays out.

  5. @LDS, it might be something which is already available in VC++, so what? Default parameters is introduced as a new feature in C# 4.0, but it’s been in Turbo Pascal and Delphi for decades!

    • No. Default parameters were not available in TurboPascal. They were introduced much later, maybe around Delphi 4 or 5, don’t remember exactly.
      Anyway as I don’t think that default parameters in C# 4.0 are an innovative feature, but was just something missing. I do not look at the delayed keyword as innovative as well. Like many improvements in this release looks like they’re at last “polishing” and “finishing” Delphi. Very good, but not something that makes me jump on my chair. They are filling the gap, not running in front of the others yet.

  6. Hmmm, as a previous commenter said, this seems like a “Half Job” solution… the grunt work still has to be done in the “consumer” code, and much easier to make a mistake when you aren’t forced to do that grunt work.

    Perhaps these sorts of things should be presented to the community for discussion BEFORE delivery, so that refinements could be considered BEFORE the final implementation has been committed to?

    It’s too late now, but I would have thought something like this would have made more sense:

    function CloseTouchInputHandle; external user32 name ‘CloseTouchInputHandle’
    conditional TestWindowsVersion
    alternate MyCloseTouchInputHandle;

    The conditional clause would require a simple function returning a Boolean. This function is called prior to the first invocation of CloseTouchInputHandle. If it returns TRUE then it binds to the external proc as normal.

    If FALSE then no binding occurs and a suitable, trappable exception is raised (rather than a random access violation or “blow up”).

    That is unless an “alternate” clause is specified.

    Where alternate is specified, the clause must refer to a procedure or function with the same signature as the subject proc (in this case , CloseTouchInputHandle) and where the conditional clause returns FALSE, the proc is bound to this alternate proc instead.

    This would have addressed the need much more directly, moving all the grunt work involved for handling such things to the implementer of the DECLARATION of the binding, rather than off-loading that grunt work to the consumer whilst simultaneously HIDING the need for the grunt work (yes, the “delayed” decoration reveals the need for the grunt work, but you have to go spelunking the declaration to discover that, presumably – or does the compiler issue warnings? I hope and guess not, because there’s no way for the compiler to determine when/whether any particular invocation of a delayed binding is potentially dangerous).

    • As said before, delayed loading is a standard PE feature and thereby IMHO it took little effort to implement it. It is handy while importing external DLLs. How to handle what happens when the DLL is not available is code-specific. Why should I mimic a whole DLL interface as the code above implies, when probably those calls are simply hidden in a class that could call totally different low-end interfaces if that DLL is not available?

  7. Actually, I don’t think it IS too late. The refinement I suggest above is useful where the provider of a declared binding to some external proc is able and willing to provide an alternate, as in the case of this Touch API.

    The “delayed” feature still has merit where the binding is entirely optional and has no direct, universal alternate.

    So my spitballing could perhaps lead to a future enhancement in this area, rather than be seen as an alternative that the current feature now precludes.

  8. Like others above, I find this extension quite of an “half-job”, and it kinda promotes runtime failures if you fail to check before calling, and forgetting to check is going to be easy.

    I agree with Thomas Mueller, a wiser variation would be that used in well-written late-binding libraries: if the proc is available assign it to a variable, if not, leave the variable nil.

    This way we can check for availability with an “if Assigned()” (which would do the same as Ulf’s CallExists() suggestion), and if not checked you can still provide a nice error message (make the call an indirect one for delayed functions, this way you can raise an exception with the name of the proc that wasn’t found).

    Btw those “if OSVersion=WINDOWS_7 then” are IME anti-patterns, as it’s not the OS version you’re actually after but the feature support (which could be added to a previous version of Windows, MS already did that many times, or third party could, as they’ve already done).
    Hence checking for the availability of the functionality rather than the OS version is always preferable.

    • I agree with Eric’s comment. delayed would be be best if it worked as a shortcut for the GetProcAddress code and we are not at all interested in OS versions, just the features supported.

      Assigned is a much better name than CallExists for checking availability. (Why didn’t I think of that 🙂

      We could even have Jolyon’s alternate option, but with no need for the condition option. Just use the alternate when GetProcAddress fails.

  9. Hopefully this same feature has been used for Direct2D, switching back to GDI+ when Direct2D is not supported
    or will Direct2D be only available on Win7, without any counterpart for other OS?

    Thx,
    g.

  10. Pingback: Личная записная

Leave a reply to Wings of Wind Cancel reply