ASyncPro 5.00 in Delphi 2010 - Range Check Error

1.5k Views Asked by At

Trying to get AsyncPro running in D2010. Using the 5.00 version from Source Forge.

The AsyncPro code (in OOMisc.pas) below is failing with a range check errror on the MakeLong line below. I don't have a clue how to start debugging this.

Does anyone have ASyncPro running in D2010, or have some insight into what might be going on below? A posting by me on the SourceForge yielded no responses.

function SafeYield : LongInt;
  {-Allow other processes a chance to run}
var
  Msg : TMsg;
begin
  SafeYield := 0;
  if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then begin
    if Msg.Message = wm_Quit then
      {Re-post quit message so main message loop will terminate}
      PostQuitMessage(Msg.WParam)
    else begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
    {Return message so caller can act on message if necessary}
    SafeYield := MAKELONG(Msg.Message, Msg.hwnd);  // Range Check Error on this line!
  end;
end;

TIA

4

There are 4 best solutions below

0
On BEST ANSWER

It seems that you compile the code with range checking on:

{$R+}
function Test(A, B: LongWord): LongInt;
begin
  Result:= MakeLong(A,B);
// Project .. raised exception class ERangeError with message 'Range check error'.
end;

You can switch range checking off to get rid off the runtime error, but the result of

SafeYield := MAKELONG(Msg.Message, Msg.hwnd)

is incorrect if one of the arguments (or both) is above 2^16 - 1.

Looks like the code was ported from 16-bit AsyncPro version without change to 32-bit version and the bug existed where through all 32-bit AsyncPro versions.

0
On

(1) That code is a Message Pump, and

(2) (in context) it is protected by a R- compiler directive. Range checking is turned off: {$R- No range checking} in AwDefine.inc

So (1) If some other message causes the code to stop, this is where it will be when the message goes through, and

(2) The range check error does not come from here.

This suggests that an asyncronous process is causing a range check exception or modal message. In the version of Delphi I am working with, range check errors (and list index messages) do not give any source/debug information, so I can only suggest that the error may be linked to an asynchronous Comm event, or even a got-focus/lost-focus/activate/paint event.

0
On

I would echo Allen's comment - but go further. If you look at how the code is being used (Look at DelayTicks also in OoMisc) callers either assume that the return value is unimportant or is JUST the message. Adding the Msg.hwnd to the number is not just not going to work, it is also not what the callers are expecting.

repeat
  if Yield then
    Res := SafeYield;
until (**Res = wm_Quit**) or TimerExpired(ET);

This code is expecting a message only.

I would change the line

 SafeYield := MAKELONG(Msg.Message, Msg.hwnd);

to

 SafeYield := Msg.Message;
0
On

Seeing as how MAKELONG takes two parameters of type Word (16bits), and Msg.Message and Msg.HWnd are both 32bits it is not surprising that you're getting range-check errors. In general, window messages are < $8000 so I doubt that value is the problem. However, the integral value of an HWnd can be all over the map and is certainly > $FFFF quite often. Because of this the above code doesn't really make sense, except that it appears to be a long-ago left over artifact from the 16bit version.

Since range-checking is enabled it is clearly highlighting the fact that the above code needs a bit of a re-think. In Win32, you cannot fit a message value and window handle into 32bits anymore.

I hope I've given you a few hints on how to proceed. Without taking into account the code that calls this function, it is not possible to suggest an alternative implementation.