GetCursorPos only returning x value - winapi

I saw a thread on an MSDN forum where there was an issue with 32-bit vs. 64-bit integers. I'm not sure if that is my issue, but it seems as though this code should work, so I'm a bit confused.
I'm running VB6 in compatiblity mode (XP SP2) in Windows 7 64-bit.
Type POINTAPI ' This holds the logical cursor information
x As Integer
y As Integer
End Type
Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
In Timer1_Timer()...
Dim mousePos As POINTAPI
Call GetCursorPos(mousePos)
MsgBox mousePos.x & " " & mousePos.y
This message box shows the correct value for the x coordinate of the mouse, but it shows "0" for y, no matter where the mouse is on the screen. Also, GetCursorPos() is returning 1.

In VB6 the Integer data type is a 16-bit number. You have to use Long as this is a 32-bit number.
Type POINTAPI ' This holds the logical cursor information
x As Long
y As Long
End Type
Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
or use:
Declare Function GetCursorPos Lib "user32.dll" (lpPoint As POINT_TYPE) As Long

If your are running in VB6 your POINTAPI declaration needs to use a Long for your point declaration:
Type POINTAPI ' This holds the logical cursor information
x As Long
y As Long
End Type
As far as returning a 1, that means you were successful:
Return Value Long -- NonZero on success, zero on failure. Sets GetLastError
"From Visual Basic Programmer's Guide to the Win32 API"

Related

VHDL: how to represent signed/unsigned as integer string when >32 bits

I am doing a bunch of DSP verification and for printing when assertions fail, I wrote these functions for signed and unsigned types:
function to_string(arg : integer) return string is
begin
return integer'image(arg);
end function;
function to_string(arg : signed) return string is
begin
return to_string(to_integer(arg));
end function;
function to_string(arg : unsigned) return string is
begin
return to_string(to_integer(arg));
end function;
However, they just broke as some of my results are larger than 32 bits wide. Is there a way in VHDL to provide an integer string representation of signed and unsigned types when they're greater than 32 bits wide? If not, can someone provide a function for providing the hex representation of these numbers to reduce the size of what is printed to the console?
Hex representation is provided for free in VHDL 2008 in the numeric_std package via the to_hstring function. to_string and to_ostring are also provided.
These functions were provided for all bit-based types in their native packages. write, owrite and hwrite are also provided for writing to a line.
The VUnit string_ops package provides such functions: https://github.com/VUnit/vunit/blob/3de8d229ca7b4ba3db395f3981a3ea107cf67c72/vunit/vhdl/string_ops/src/string_ops.vhd#L611.

Cannot find what is wrong with the array declaration

It says
fatal: syntax error, OF expected but [ found" for the variable "lo"
But I really can't see whats wrong with it.
I tried to change variable name but seems not working.
procedure reg( index, gen : char;
fname, sname, loginname, passwords, pid : string;
var lo : array [1..26,1..1025] of bucket ;
var main : array[1..1025] of detail);
var
convertedindex, i, j : integer;
found, found2 : boolean;
It's supposed to be without error but it says syntax error.
You can't define an array while you are in the middle of declaring the parameters of a procedure (or function). You need to define the array type beforehand by doing something like this instead:
program arraydecl;
type
Bucket = integer;
Detail = integer;
type
BucketArray = array [1..26,1..1025] of Bucket;
DetailArray = array[1..1025] of Detail;
procedure reg(index, gen : char; fname, sname, loginname, passwords, pid : string ; var lo : BucketArray; var main : DetailArray);
begin
end;
The error message says that the compiler expected the keyword of, but instead it found an opening bracket [.
The reason is (I guess) that in procedure declarations, you cannot define the bounds of an array. For example, you cannot say main: array[1..2] of integer, you can only say main: array of integer.
You can try to define an array type and then use that type as the procedure parameter:
type TwoInts = array[1..2] of integer;
procedure PrintTwoInts(ti: TwoInts)
begin
WriteLn(ti[1], ti[2])
end;
I haven't programmed in Pascal for a long time, so the above may or may not work. I don't remember whether ti would be passed by value or by reference, and whether the array indices inside the procedure would always start at 0. That's some things you would need to find out.
Parameter lists
In some Pascal versions, like FreePascal or Delphi, parameter lists of functions or procedures cannot contain type declarations, only type specifications.
So, to specify such an array as parameter, you must declare its type first, before the function/procedure declaration:
type
// Type declarations
Bucket = ...
Detail = ...
TBuckets = array[1..26, 1..1025] of Bucket;
TDetails = array[1..1025] of Detail;
procedure Reg(Index, Gen: Char; FName, SName, LoginName, Passwords, PID: string;
var Lo: TBuckets; var Main: TDetails);
Note that other Pascals (including ISO Pascal, if I remember correctly) do allow these ad hoc (on the spot) declarations, even in parameter lists. But obviously your dialect of Pascal doesn't.
Open array parameters
Now if you see a parameter specifications like x: array of Integer or similar, then you are dealing with open array parameters. This is not a declaration and it doesn't specify one single type, it accepts all kinds of one-dimensional arrays of that base type. More on that in my article Open array parameters and array of const.
This explains the error message: only of can follow array in a parameter list, to specify an open array parameter.
For what it's worth: if you are using FreePascal or Delphi, then you should get in the habit of passing strings as const, if possible: const FName, SName, etc...: string.

Delphi: custom window menu: Msg.CmdType and $FFF0 clarification needed

I am doing some finishing touches on my Windows application developed in Delphi XE6.
Currently, I become confused about window system menu, I mean the menu that appears when you click onto the icon in the title bar on the left.
I have defined two procedures:
// this inserts one additional command into the menu
procedure InsertCommand(Sender: TObject);
// this is obviously a handler of mouse clicks on that menu
procedure OnSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
The definitions follow:
const
ALWAYS_ON_TOP_ID = 1000;
var
HandleMenu: THandle;
sAlwaysOnTop: string;
procedure TFormMain.InsertCommand(Sender: TObject);
begin
// get the system menu handle and store it into form-level defined variable
HandleMenu := GetSystemMenu(Handle, False);
// just to make it nicer, I add a separator line
AppendMenu(HandleMenu, MF_SEPARATOR, 0, '');
// append "Always on Top" language localized string at the end of the menu
AppendMenu(HandleMenu, MF_STRING, ALWAYS_ON_TOP_ID, PChar(sAlwaysOnTop));
end;
procedure TFormMain.OnSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType = ALWAYS_ON_TOP_ID then
if GetMenuState(HandleMenu, ALWAYS_ON_TOP_ID, MF_BYCOMMAND) and MF_CHECKED = MF_CHECKED
then begin
FormStyle := fsNormal;
CheckMenuItem(HandleMenu, ALWAYS_ON_TOP_ID, MF_UNCHECKED);
end else begin
FormStyle := fsStayOnTop;
CheckMenuItem(HandleMenu, ALWAYS_ON_TOP_ID, MF_CHECKED);
end;
inherited;
end;
I now read that the right usage is:
Msg.CmdType and $FFF0
but if I use that, my code stops working.
From the official MSDN source, I quote:
In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system. To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.
Question is, do I have to avoid the $FFF0 mask, or is there a more proper way?
The documentation is accurate, the reason your code stops working when you test bitwise AND with $FFF0 is the constant you define is no good.
const
ALWAYS_ON_TOP_ID = 1000;
1000 in hexadecimal is 3E8, the lowest order hexadecimal digit should be 0 for the lowest four bits to be 0. IOW, binary 1111 is hexadecimal F, so you should leave the last digit to the system.
Set your constant in hexadecimal so you won't make a mistake. Just be careful to stay clear off the SC_... range (which is $F000 ... $F###) when defining your constant. E.g.:
const
ALWAYS_ON_TOP_ID = $100; {256}
so now you can safely test
if Msg.CmdType and $FFF0 = ALWAYS_ON_TOP_ID then
...

I am converting vb4 16 bit application to vb6 32 bit application. How to convert librarys

I have vb4 16bit app. I want to convert these two libraries...
Declare Function IsCharLower Lib "User" (ByVal cChar As Integer) As Integer
Declare Function IsCharUpper Lib "User" (ByVal cChar As Integer) As Integer
I want to convert to vb6 32 bit
How to do that
User in VB4 is User32 in VB6 (and other Windows languages that refer to it).
Declare Function IsCharLower Lib "User32" (ByVal cChar As Integer) As Integer
Declare Function IsCharUpper Lib "User32" (ByVal cChar As Integer) As Integer
IsCharLower documentation
IsCharUpper documentation

Is it possible to debug a COM dll in VS2008?

This may be a very stupid question.
Is it possible to debug a COM dll in VS2008 for which I do not have the source code?
The reason I want to do this is I am passing an Array to a COM method and I expect this Array to be populated by the method.
However the Array is not being populated. So I want to step into the COM method to see whats happening. is this possible?
Below is an example of the code I am using:
Array binaryArray = Array.CreateInstance(typeof(sbyte), 896);
bool success = photo.GetBinaryData(binaryArray);
IDL for the GetBinaryData method:
[id(0x000000c9)]
HRESULT GetBinaryData(
[in] SAFEARRAY(char) buffer,
[out, retval] VARIANT_BOOL* retval);
The GetBinaryData method is the COM method which I would like to step into.
EDIT: Adding a Delphi test script which works
procedure TComTestForm.TestUserBtnClick(Sender: TObject);
var
nCnt :integer;
User :IUser;
Persona :IUserPersona;
ArrayBounds :TSafeArrayBound;
ArrayData :Pointer;
TagList :PSafeArray;
nSize :integer;
begin
User := Session.GetUser;
ArrayBounds.lLbound := 0;
ArrayBounds.cElements := 0;
TagList := SafeArrayCreate( varInteger, 1, ArrayBounds );
User.GetTags( TagList );
if SafeArrayAccessData( TagList, ArrayData ) = S_OK then
begin
nSize := TagList.rgsabound[0].cElements;
OutLine( '----Available Tags, ' + IntToStr(nSize) + ' tags' );
for nCnt := 0 to nSize - 1 do
begin
OutLine( IntToStr( IntegerArray(ArrayData)[nCnt] ) );
end;
OutLine( '----');
SafeArrayUnAccessData( TagList );
SafeArrayDestroy( TagList );
end;
end;
In principle, yes, you can step through the code of the COM method implementation instruction-by-instruction.
However, even if you know assembly well and understand exactly how all the processor instructions work, it's a tall order to debug someone else's code in this fashion unless it's a really, really simple method.
If you are new to assembler, don't even consider it unless you're prepared to do weeks of learning curve first.
If the COM method doesn't appear to be working in the way you expected based on its documentation, I would first try to test the method using unmanaged code (e.g. C++), as your problem may be in the COM Interop marshalling rather than in the COM method itself.

Resources