 |
Bay Six Software Beyond the Basics
|
View previous topic :: View next topic |
Author |
Message |
Mattestion New Member
Joined: 29 Feb 2012 Posts: 4
|
Posted: May 12th, 2012, 12:18pm Post subject: Limit a window's minimum size |
|
|
I've been trying to use the VB code at this Microsoft article support.microsoft.com/kb/185733. I get the protection violation error and I know it's because I'm not calling the RtlMoveMemory function correctly. But I can't figure out how to do it. In the VB code, it uses type long for the parameters but the MSDN article says to use pointers.
Here is my code:
Code: |
struct MINMAXINFO,_
ptReserved.x as long,_
ptReserved.y as long,_
ptMaxSize.x as long,_
ptMaxSize.y as long,_
ptMaxPosition.x as long,_
ptMaxPosition.y as long,_
ptMinTrackSize.x as long,_
ptMinTrackSize.y as long,_
ptMaxTrackSize.x as long,_
ptMaxTrackSize.y as long
open "WMLiberty" for dll as #wmlib
nomainwin
WindowWidth = 800
WindowHeight = 600
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
open "Limited Min" for window as #min
#min "trapclose [QUIT]"
callback lpfn, OnGetMinMaxInfo(ulong, ulong, ulong, ulong), long
hwndMin = hwnd(#min)
calldll #wmlib, "SetWMHandler", _
hwndMin as ulong, _
_WM_GETMINMAXINFO as ulong, _
lpfn as ulong, _
0 as long, _
ret as long
[LOOP]
scan
calldll #kernel32, "Sleep", _ 'Minimize CPU usage
50 as long, _
ret as void
goto [LOOP]
[QUIT]
close #min
close #wmlib
end
function OnGetMinMaxInfo(hwnd, uMsg, wParam, lParam)
length = len(MINMAXINFO.struct)
calldll #kernel32, "RtlMoveMemory", MINMAXINFO as struct, lParam as ulong, length as long
ptMinTrackSize.x.struct = 400
ptMinTrackSize.y.struct = 300
length = len(MINMAXINFO.struct)
calldll #kernel32, "RtlMoveMemory", lParam as ulong, MINMAXINFO as struct, length as long
end function
|
_________________ Just BASIC v1.01 / Liberty BASIC Pro v4.04 / Run BASIC v1.01 / Vista Home Premium SP2 - AMD Athlon 64 X2 Dual Core Processor 5000+ 2.60 GHz - 2GB RAM |
|
Back to top |
|
 |
STPendl Full Member
Joined: 20 Aug 2007 Posts: 161 Location: Austria
|
Posted: May 12th, 2012, 1:24pm Post subject: Re: Limit a window's minimum size |
|
|
VB is bad since they use LONG for anything and convert it to the correct data-type behind the scene.
It is always best to translate from an ANSI C code source to LB, since they do have more in common in regard to data-types.
In addition you are missing an argument of the function, which must be present.
See RtlMoveMemory at MSDN for the correct declaration.
Code: |
calldll #kernel32, "RtlMoveMemory", _
Destination as struct,_
Source as ulong, _
SourceLength as ulong, _
Result as void
|
Depending on the type of the source and destination, you use ULONG (Windows memory location address) or STRUCT (LB structure). _________________ Stefan
Any code I post can be freely used, just give credit. |
|
Back to top |
|
 |
Mattestion New Member
Joined: 29 Feb 2012 Posts: 4
|
Posted: May 13th, 2012, 12:20am Post subject: Re: Limit a window's minimum size |
|
|
Quote: | It is always best to translate from an ANSI C code source to LB |
That's my feeling as well but I couldn't find any code in C. All the forums kept saying to respond to the WM_GETMINMAXINFO message and fill in the MINMAXINFO struct but they never gave any code.
Quote: | In addition you are missing an argument of the function |
Doh! I can't believe I forgot the Result argument. I also forgot that you can't fill in the struct like this:
Code: |
ptMinTrackSize.x.struct = 400
ptMinTrackSize.y.struct = 300
|
It needs the name of the struct like this:
Code: |
MINMAXINFO.ptMinTrackSize.x.struct = 400
MINMAXINFO.ptMinTrackSize.y.struct = 300
|
Thanks Stefan for your help with the data types. It works great now. Here is the corrected code:
Code: |
struct MINMAXINFO,_
ptReserved.x as long,_
ptReserved.y as long,_
ptMaxSize.x as long,_
ptMaxSize.y as long,_
ptMaxPosition.x as long,_
ptMaxPosition.y as long,_
ptMinTrackSize.x as long,_
ptMinTrackSize.y as long,_
ptMaxTrackSize.x as long,_
ptMaxTrackSize.y as long
open "WMLiberty" for dll as #wmlib
nomainwin
WindowWidth = 800
WindowHeight = 600
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
open "Limited Min" for window as #min
#min "trapclose [QUIT]"
callback lpfn, OnGetMinMaxInfo(ulong, ulong, ulong, ulong), long
hwndMin = hwnd(#min)
calldll #wmlib, "SetWMHandler", _
hwndMin as ulong, _
_WM_GETMINMAXINFO as ulong, _
lpfn as ulong, _
0 as long, _
ret as long
[LOOP]
scan
calldll #kernel32, "Sleep", _ 'Minimize CPU usage
50 as long, _
ret as void
goto [LOOP]
[QUIT]
close #min
close #wmlib
end
function OnGetMinMaxInfo(hwnd, uMsg, wParam, lParam)
length = len(MINMAXINFO.struct)
calldll #kernel32, "RtlMoveMemory", MINMAXINFO as struct, lParam as ulong, length as ulong, result as void
MINMAXINFO.ptMinTrackSize.x.struct = 400
MINMAXINFO.ptMinTrackSize.y.struct = 300
length = len(MINMAXINFO.struct)
calldll #kernel32, "RtlMoveMemory", lParam as ulong, MINMAXINFO as struct, length as ulong, result as void
end function
|
_________________ Just BASIC v1.01 / Liberty BASIC Pro v4.04 / Run BASIC v1.01 / Vista Home Premium SP2 - AMD Athlon 64 X2 Dual Core Processor 5000+ 2.60 GHz - 2GB RAM |
|
Back to top |
|
 |
STPendl Full Member
Joined: 20 Aug 2007 Posts: 161 Location: Austria
|
Posted: May 13th, 2012, 9:08am Post subject: Re: Limit a window's minimum size |
|
|
Another way would be using the RESIZEHANDLER, but that only works for windows of type window.
For dialog type windows you could use the approach I used for my LB 4.04 help search entry. _________________ Stefan
Any code I post can be freely used, just give credit. |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: May 13th, 2012, 2:38pm Post subject: Re: Limit a window's minimum size |
|
|
STPendl wrote: | VB is bad since they use LONG for anything and convert it to the correct data-type behind the scene.
It is always best to translate from an ANSI C code source to LB, since they do have more in common in regard to data-types. |
It makes not the slightest difference whether you specify LONG or ULONG in a STRUCT declaration or a CALLDLL statement, so long as the actual value is valid for both (which means it is in the range 0 to +2147483647). Only if the value is negative (in which case you must use LONG) or greater than +2147483647 (in which case you must use ULONG) does it matter.
So for example in the case of the RtlMoveMemory API you can be absolutely certain that the length parameter is valid for both LONG and ULONG, and it makes no difference which you use.
Richard. |
|
Back to top |
|
 |
Alyce Full Member
Joined: 04 Jul 2005 Posts: 91
|
Posted: May 14th, 2012, 12:32pm Post subject: Re: Limit a window's minimum size |
|
|
RichardRussell wrote: |
It makes not the slightest difference whether you specify LONG or ULONG in a STRUCT declaration or a CALLDLL statement, so long as the actual value is valid for both
Richard. |
That is not correct for Liberty BASIC. You may not know the "actual value" returned from the HWND statement, for instance. If you pass it as a long into an API call it might be misinterpreted. This has happened to folks and caused errors that are hard to nail down.
Stefan is correct when he cautions folks to use C rather than VB for documentation on API functions. _________________ - Alyce |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: May 14th, 2012, 1:29pm Post subject: Re: Limit a window's minimum size |
|
|
Alyce wrote: | That is not correct for Liberty BASIC. You may not know the "actual value" returned from the HWND statement, for instance. |
It is always correct; the language makes no difference. There are basically three situations that you can encounter in Liberty BASIC:
1. The value that you are storing in a STRUCT, or passing in a CALLDLL statement, is known (for example it may be a constant that you set in your program). In that case you can easily determine what type to use: if it's negative you must declare it as LONG, if it's greater than +2147483647 you must declare it as a ULONG. Otherwise it makes no difference, you can use LONG or ULONG.
2. The value that you are storing in a STRUCT, or passing in a CALLDLL, was itself returned from a previous API call. In that case what matters is that the type you specified for the value returned from the original API is the same as the type you specify in the STRUCT or CALLDLL. It doesn't matter whether it's LONG or ULONG, but they must agree. So for example both these code snippets are perfectly correct:
Code: | calldll #user32, "GetDesktopWindow", hdesk as LONG
calldll #user32, "GetWindowDC", hdesk as LONG, hdc as LONG
calldll #user32, "GetDesktopWindow", hdesk as ULONG
calldll #user32, "GetWindowDC", hdesk as ULONG, hdc as ULONG |
A myth has developed at some stage that you must always use ULONG for handles, but that is not true. In a case such as the code above all that matters is that the type specified when the handle is retrieved is the same as that when it is subsequently used.
3. The value is a handle returned from HWND(). When passing the handle to CALLDLL or storing it in a STRUCT you must use whatever type is returned from HWND(). The trouble is that the LB docs don't tell you what that is! I assume that it's a ULONG, in which case that's the type you should specify in the STRUCT or CALLDLL. But it would be a lot more helpful it that was stated somewhere.
What's important to realise is that the type specified in (say) the Microsoft documentation for an API is never important in LB. When LB calls an API it simply passes numbers, there is no way that Windows can tell or care what type was assigned to that number in LB. I read Stefan's comment as implying the contrary - that somehow it can be important to specify in your LB program the type that MSDN specifies rather than the type the VB docs specify. That is not correct and it can lead to a misunderstanding about how the interface between an application and the Windows API works.
Richard. |
|
Back to top |
|
 |
Alyce Full Member
Joined: 04 Jul 2005 Posts: 91
|
Posted: May 14th, 2012, 2:16pm Post subject: Re: Limit a window's minimum size |
|
|
RichardRussell wrote: |
A myth has developed at some stage that you must always use ULONG for handles, but that is not true. |
The "myth" developed because Carl stated it to be so. Since he is the author of the language, I trust he knows how types are handled behind the scenes.
Quote: | 3. The value is a handle returned from HWND(). When passing the handle to CALLDLL or storing it in a STRUCT you must use whatever type is returned from HWND(). The trouble is that the LB docs don't tell you what that is! I assume that it's a ULONG, in which case that's the type you should specify in the STRUCT or CALLDLL. But it would be a lot more helpful it that was stated somewhere.  |
As I wrote above, it is type ulong. It should be stated in the docs. Considering the fact that Carl must make a living at a full-time job and must develop LB by himself in whatever spare time he can find, I think he does an excellent job. He did a better job when he could devote 100% of his working hours to LB. That has not been the case for years, though.
I don't disagree that you can pass a number as either ulong or long as long as it fits within the values of the type specified. Liberty BASIC is meant to be beginner-friendly, hobbiest-friendly. Since Carl tells us that handles are always to be of type ulong, it is much easier to pass them as ulong than to put in conditional statements to check if they are within a certain range of numbers so that they can be passed as longs. _________________ - Alyce |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: May 14th, 2012, 5:16pm Post subject: Re: Limit a window's minimum size |
|
|
Alyce wrote: | The "myth" developed because Carl stated it to be so. Since he is the author of the language, I trust he knows how types are handled behind the scenes. |
I don't know the context in which he stated that, but I expect he was referring to the type returned by HWND(), which may well be a ULONG.
Given that being the case, I have no objection to advising users of LB always to use ULONG for handles, because it's a nice easy-to-remember rule, and as you rightly say LB is intended to be simple for beginners.
However I still think it is important to appreciate that it's only essential to use ULONG when the handle was returned from HWND(). When it is returned from an API function all that matters is that the same type (LONG or ULONG) is used consistently for that handle.
I'm not trying to second-guess how LB is implemented, and certainly not suggesting that Carl is mistaken, but simply stating a fundamental fact which follows from the way all applications interface with the Windows API.
Quote: | Considering the fact that Carl must make a living at a full-time job and must develop LB by himself in whatever spare time he can find, I think he does an excellent job. |
No criticism of Carl was intended or implied. I would prefer the docs to be more comprehensive and more accurate, but I can understand Carl wishing to concentrate his time on coding rather than writing documentation. The user community can go a long way to address the deficiencies in the docs.
I'm fortunate in having now retired so I don't have to divide my time between paid employment and 'hobby' programming. However for about 25 years I was in exactly the same position as Carl: working full-time for an employer and developing/documenting/marketing BBC BASIC in my spare time. So I know what the pressures are.
Richard. |
|
Back to top |
|
 |
STPendl Full Member
Joined: 20 Aug 2007 Posts: 161 Location: Austria
|
Posted: May 14th, 2012, 5:57pm Post subject: Re: Limit a window's minimum size |
|
|
The whole thing started out with Windows XP, when more handles were used by the system and they got beyond the positive range of LONG.
This has caused some real trouble, since stable API functions started crashing unexpectedly.
The conclusion was to use ULONG instead of LONG for handles, which resulted in more stable code.
In general a handle can never be a negative number, since it ranges from 0 to 2^32.
One can argue that the binary representation is the same, but we want to develop on the save side.
And if anyone is turning this into a bug of LB and an advantage of any other tool, he should turn his face into the next corner and think about what he has done wrong. _________________ Stefan
Any code I post can be freely used, just give credit. |
|
Back to top |
|
 |
RichardRussell Full Member
Joined: 28 Jan 2012 Posts: 57 Location: Downham Market, UK
|
Posted: May 14th, 2012, 9:26pm Post subject: Re: Limit a window's minimum size |
|
|
STPendl wrote: | In general a handle can never be a negative number, since it ranges from 0 to 2^32. |
A handle is a 32-bit number. As far as Windows and the processor is concerned there is no concept of it being positive or negative.
In the Windows header files HANDLE is defined as void*, i.e. as a pointer to void. It is neither signed nor unsigned, indeed strictly it's not even an integer! That may be why LB supports the undocumented type HANDLE:
Code: | calldll #user32, "GetDesktopWindow", hdesk as HANDLE
calldll #user32, "GetWindowDC", hdesk as HANDLE, hdc as HANDLE |
Richard. |
|
Back to top |
|
 |
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|
|