-2

enter image description here

Migrating delphi Win32 code to Win64 with Delphi code, especially when using event handlers or an function taking a TPoint parameter: in Win32 this showed correct values for the point’s x and y coordinates, but in Win64 reading x and y gave ‘junk’ values or some time same as value pass to it.

In my case TDM_Point(Msg.lParam) Msg.lParam do have value {3997726 } and after casting to TPoint variable P contain { x=30,y=61} in win32 bit and in win64 Msg.lParam do have value {3997726 } as same in win32 but after casting to TPoint variable P contain {x=3997723,y=0} )

Conditional defined as follows:

{$IFDEF WIN32}
    TDM_Point = TSmallPoint;
{$ELSE}
    TDM_Point = TPoint;
{$ENDIF}

Sample code as follows :

Function process
begin
  If Form.Handle = Msg.hWnd Then
  begin
    Control := SearchControl ( Form, TDM_Point(Msg.lParam) );         
    //Msg is type of tagMSG 
  end
end


Function Form.SearchControl ( Parent : tWinControl; P : TDM_Point ) : tControl;
Var
  Index   : Integer;
  Control : tControl;
  Rect    : tRect;
  tmpPoint : TPoint;
Begin            
  //code            
end 

Msg value is set by value return by Process Message

[UIPermission(SecurityAction.LinkDemand, Window=UIPermissionWindow.AllWindows)]
procedure TApplication.HandleMessage;
var
  Msg: TMsg;
begin
  if not ProcessMessage(Msg) then Idle(Msg);
end;  

Value is set as follows :

If Drawing Then
Begin
{$IFNDEF WIN32}
  { Map coordinates to parent of chosen control,
    or to form in no control is chosen }
  If EditControls.Count > 0 Then
     MapWindowPoints ( Msg.hWnd,
                       tControl(EditControls.Objects[0]).Parent.Handle,
                       Msg.lParam, 1 )
  Else
     MapWindowPoints ( Msg.hWnd, fEditForm.Handle,
                       Msg.lParam, 1 );
{$ELSE}
  x:=GetSystemMetrics(SM_CXFRAME);
  if abs((Msg.Pt.X-fEditForm.left-x) - TDM_Point(Msg.lParam).X)  > 0 then
    TDM_Point(Msg.lParam).X:=Msg.Pt.X-fEditForm.left-x;

  x:=GetSystemMetrics(SM_CYCAPTION)+GetSystemMetrics(SM_CYFRAME);
  if abs((Msg.Pt.Y-fEditForm.top-x) - TDM_Point(Msg.lParam).Y)  > 0 then
    TDM_Point(Msg.lParam).Y:=Msg.Pt.Y-fEditForm.top-x;
{$ENDIF}
  Start.X   := TDM_Point(Msg.lParam).X;
  Start.Y   := TDM_Point(Msg.lParam).Y;
  Last    := Start;
  SetSelection;
  SetClipRect;
End;      

please find the call stack below. we did not prepare any message. this is prepared by system when we click on label control of the form. top two functions of call stack are our functions,in which we get the msg value from processmessage of vcl.forms
msgruntimevalue

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
  • 1
    Somewhat hard to work out what is going on here given the scraps of code. A definitive answer will be simple to provide once you offer a [mcve]. – David Heffernan Dec 10 '18 at 09:15
  • 3997726 is hex $003D001E which looks like two 16 bit values (two Smallints), X = $1E = 30, Y = $3D = 61. Obviously you are receiving a TSmallPoint as Msg.lParam, even in Win64. So always cast to TSmallPoint, never cast to TPoint. Usually, such items are passed by reference anyway. A [MCVE] could tell us more. – Rudy Velthuis Dec 10 '18 at 11:30
  • 2
    Your edit doesn't really help, it does not address where the value of lParam is set. Why won't you just make a [mcve]? Please answer that question. – David Heffernan Dec 10 '18 at 13:26
  • @David: but we know that, also in Win64, the value of lParam is 3997726 (= $003D001E), which are exactly the values 61 and 30 in 2 x 16 bit. So that seems to be a TSmallPoint too. – Rudy Velthuis Dec 11 '18 at 09:03
  • @RudyVelthuis But that's no way to program is it. As a professional programmer, I would certainly not write programs based on reverse engineering. I'd consult the documentation. Consider also the matter of pedagogy, we have an opportunity to teach the asker how better to solve problems, and present questions, which will help he/she become a better programmer. That's why I spend time here. – David Heffernan Dec 11 '18 at 09:08
  • Your screen shot shows an lParam of $003E0021, which indicates a TSmallPoint of X = $0021 = 33, Y = $003E = 62. Again, you never receive a TPoint, so your coinditional define of TDM_Point is wrong. **It is always a TSmallPoint, and not a TPoint**. – Rudy Velthuis Dec 11 '18 at 09:09
  • @David: neither would I. But sometimes (e.g. when I wrote the VCL Component Installer that is now part of the Delphi IDE) you must live with incomplete documentation and then you must reverse engineer or experiment. That is not what I prefer, but sometimes you have no choice. I don't know if OP has that choice. One way to solve a lack of documentation is to reverse engineer the values we receive. $3D001E is obviously a combination of two 16 bit values (we know they should be 30 and 61). But of course, OP should first look for any documentation on the messages he receives. – Rudy Velthuis Dec 11 '18 at 09:11
  • @Rudy Well, it seems like it's an event handler for `WM_LBUTTONDOWN` given the message ID, and so there's no need for any guesswork. This is what I was asking for all along. – David Heffernan Dec 11 '18 at 09:19
  • Hmmm... looked up the WM_ value of $201, which is WM_LBUTTONDOWN. And that is properly documented. So OP should simply read that. And then we see that the lParam contains two 16 bit words. – Rudy Velthuis Dec 11 '18 at 09:19
  • @kishor You seem to be handling `WM_LBUTTONDOWN`. Where is the code that shows you receiving that message. – David Heffernan Dec 11 '18 at 09:19
  • After the comments and answers of yesterday, the problem should already be evident. Something seems to be holding up the poster to acknowledge that there's no TPoint. @kishor, you don't have any TPoint in lParam, not in 32 bit, not in 64 bit. – Sertac Akyuz Dec 11 '18 at 10:29

2 Answers2

1

The conditional define you use is wrong: You say that Msg.lParam is 3997726 in both cases. That can only mean one thing: you always receive a TSmallPoint, and never a TPoint.

3997726 is hex $003D001E which shows 16 bit values (two Smallint values),

X = $001E (decimal value 30) 
Y = $003D (decimal value 61). 

Obviously you are receiving a TSmallPoint as Msg.lParam, even in Win64. So always cast to TSmallPoint, never cast to TPoint (I can't imagine you cast to to TPoint in Win32, you probably cast to TDM_Point).

Since Msg.lParam is 64 bit in Win64, you can't directly cast it to TDM_Point[1] (or to TSmallPoint) — I guess that is why you made it a TPoint in Win64: to match the size of Msg.lParam.

But integral types of different sizes can be cast to each other. So you can use an intermediate cast to an integral type of the right size (UInt32 here, which is a 32 bit unsigned integer), e.g. something like:

type
  // No conditional define! Always TSmallPoint!
  TDM_Point = TSmallPoint; // 2 x 16 bit = 32 bit

and later on in your code:

begin
  X := TDM_Point(UInt32(Msg.lParam)).X; // or: TSmallPoint(UInt32(Msg.lParam)).X
  Y := TDM_Point(UInt32(Msg.lParam)).Y; // or: TSmallPoint(UInt32(Msg.lParam)).Y

So again: the message you receive always seems to contain a TSmallPoint. Do not define TDM_Point differently for different platforms.

UPDATE

The screenshot you added shows that the message is WM_LBUTTONDOWN, which is very well documented:

lParam

The low-order word specifies the x-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area.

The high-order word specifies the y-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area.


[1] As David Heffernan confirmed.

Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
  • You can't make such a cast. Such a cast requires that both types are the same size. – David Heffernan Dec 10 '18 at 12:33
  • You can cast one integral type to another. So you can cast UInt32(MyUint64) or Byte(MyUint32) etc. That will cut off the high part, but it is possible. Equally, UInt64(myUInt32) can be cast too. And then you can cast TSmallPoint(UInt32), since they *are* of the same size. – Rudy Velthuis Dec 10 '18 at 14:36
  • Let's stay on topic here. In this question we are casting between a record and an integral type. Your answer states that you are not sure whether these casts can be made with different sized types. My comment was intended to fill in the missing knowledge for you. – David Heffernan Dec 10 '18 at 14:38
  • Ah, Ok, then thanks. That was what I expected. Hence the intermediate cast to UInt32. – Rudy Velthuis Dec 10 '18 at 14:39
  • please see conditional define code.TDM_POINT is nothing but TPOINT (64 bit application -long int) and TSMALLPOINT(32bit application -smallInt) {$IFDEF WIN32} TDM_Point = TSmallPoint; {$ELSE} TDM_Point = TPoint; {$ENDIF} –  Dec 11 '18 at 05:49
  • ***The conditional define is wrong***. You **obviously** always receive a TSmallPoint. Otherwise Msg.lParam could not be 3997726 (I explained what this number is in hex and that this is two 16 bit values, IOW a TSmallpoint). Please read my answer again nd try to understand it. Again: 3997726 is hex $003D001E which are two 16 bit values (X=30 and Y=61), hence a TSmallpoint. The conditional define is wrong. – Rudy Velthuis Dec 11 '18 at 08:30
0

The reason why this is happening is becouse TSmallPoint is a recoed whose X and Y fields are stored as Smallint (16 bit integer) while TPoint stores its X and Y fields as FixedInt (32 bit integer)

System.Types.TSmallPoint

System.Types.TPoint

Internal Data Formats (Delphi)

So when you are typecasting your data to TPoint structure in your 64 bit application reading X value actually reads memory block that holds both X and Y values especially if the messege was created in 32 bit application which uses TSmallPoint structure.

Therefore in order to solve your problem you will have to unify your data structure on both 32 bit and 64 version of your application in order to be able to send messages between the two of them.

SilverWarior
  • 7,372
  • 2
  • 16
  • 22
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/185092/discussion-on-answer-by-silverwarior-a-tpoint-parameter-shows-correct-values-in). – Samuel Liew Dec 11 '18 at 22:14