Windows Programming: Learning more about the Win32® API.
Handling Win API Constants
PB will instantly recognize Win API constants if you preceed them with the "#" (pound) character, just as it instantly recognizes Win API procedures if you trail them with a "_" (underscord) character.
Example:
GetStdHandle() in Win32 Help becomes GetStdHandle_()
STD_INPUT_HANDLE in Win32 becomes #STD_INPUT_HANDLE ;Standard input handle
STD_OUTPUT_HANDLE in Win32 becomes #STD_OUTPUT_HANDLE ;Standard output handle
STD_ERROR_HANDLE in Win32 becomes #STD_ERROR_HANDLE ;Standard error handle
Example:
GetStdHandle() in Win32 Help becomes GetStdHandle_()
STD_INPUT_HANDLE in Win32 becomes #STD_INPUT_HANDLE ;Standard input handle
STD_OUTPUT_HANDLE in Win32 becomes #STD_OUTPUT_HANDLE ;Standard output handle
STD_ERROR_HANDLE in Win32 becomes #STD_ERROR_HANDLE ;Standard error handle
has-been wanna-be (You may not agree with what I say, but it will make you think).
@oldefoxx: Ofcourse its as simple as that. The Win32 API constants like S_OK is predefined in PureBasic, so because it is a constant, you HAVE to add the # character in front of it, so the compiler recognizes it as a CONSTANT and NOT as a VARIABLE.
So when you just use the constant name without the #, then the compiler searches for a declaration of the variable.
So when you just use the constant name without the #, then the compiler searches for a declaration of the variable.
Exactly.
II have recently been involved in a long internet search for my recluse of a brother. It's way past the time he usually goes before contacting us, and as we get older, the risk that something bad has happened to him increases.
His emails, infrequent, never give any real details about his life. He might say something like: "I'm recovering at home. Nothing else new." And that would be the whole of his email.
As I told my sister, "Dave never bothers to relate what he already knows."
Which includes his address, phone number, state of health, what he is recovering from, what the prognoses might be, and so on. And his email address usually changes from one email to the next. I think he creates a new account each time he decides to send an email, and never bothers to use an existing account again, does not even check it for email trying to reach him.
To me, that is about the ultimate in non-consideration when it comes to being "in touch" with the interests of others. But there are many posters who are equally "out of touch" when it comes to their audience, who may be at a total loss of whatever the @#$% you are talking about.
II have recently been involved in a long internet search for my recluse of a brother. It's way past the time he usually goes before contacting us, and as we get older, the risk that something bad has happened to him increases.
His emails, infrequent, never give any real details about his life. He might say something like: "I'm recovering at home. Nothing else new." And that would be the whole of his email.
As I told my sister, "Dave never bothers to relate what he already knows."
Which includes his address, phone number, state of health, what he is recovering from, what the prognoses might be, and so on. And his email address usually changes from one email to the next. I think he creates a new account each time he decides to send an email, and never bothers to use an existing account again, does not even check it for email trying to reach him.
To me, that is about the ultimate in non-consideration when it comes to being "in touch" with the interests of others. But there are many posters who are equally "out of touch" when it comes to their audience, who may be at a total loss of whatever the @#$% you are talking about.
has-been wanna-be (You may not agree with what I say, but it will make you think).
Okay, next question: How to you relate to a TYPE structure that is used by
the Windows API, without needlessly recreating a new set of Structure and
StructureUnion types? While I wait for someone else to post an answer, I
guess I will do some experimenting on my own.
the Windows API, without needlessly recreating a new set of Structure and
StructureUnion types? While I wait for someone else to post an answer, I
guess I will do some experimenting on my own.
has-been wanna-be (You may not agree with what I say, but it will make you think).
Okay, I think I have that one too.
To refer to an existing Structure found in the Windows API, you just need to define something like X.structype, where structype is the named type in the Windows API. Most Windows references use the word TYPE instead of the PureBasic's term of Structure, and UNION instead of PB's use of both Structure plus StructureUnion within that structure.
Here is the way the Win32.Hlp describes Small_Rect, which is a structure:
Now, right away, we see some problems in trying to use this structure. First, what is a SHORT? Timo Harter produced a file called WinTypes.txt that explains how most Window types can be converted into PureBasic types. It's internal name is "How to use Windows API Types with PureBasic". According to this source, a C/C++ SHORT converts into a WORD type in PB. So instead of saying SHORT Left, we would say Left.w in our structure.
But this brings up another problem, which is that PureBasic has a set of reserved words, and both Left() and Right() are functions in PureBasic. So does naming some fields in this structure the same way cause a problem? To some compilers, such as PowerBasic, it does, because keywords there are universally exclusive, meaning that the context of use ia not considered. Fortunately, this is not true of PureBasic. So no problem there.
The "typedef struc" is actually just "Structure" in Purebasic. the "//" just represents a ";", or comment in PureBasic syntax. The "}" (right curly bracket) near the bottom represents the "EndStructure" statement in PureBasic. So to convert the above into the equivalent format in PureBasic, you would end up with this:
Note that we dropped the leading underscore to the structure name and the opening curly bracket ({). The information in the Win32.Hlp file is written to support C and C++ programmers, and the syntax they use may seem a bit arcane to PureBasic programmers (or vice versa).
C and C++ are case-sensitive programming languages, and the underscore in front of the structure name is suppose to make it suitable for export. PowerBasic does not require the underscore, and names of variables, structures, and fields are case insensitive.
The really neat thing though, is that PureBasic does not require you to create this structure in your own code - you have access to it by virtue of the power of PureBasic to resolve references to structures defined by the Win32 API automatically. But understanding how C/C++ types convert to PureBasic syntax is necessary in order to make use of them and the fields that they represent.
To refer to an existing Structure found in the Windows API, you just need to define something like X.structype, where structype is the named type in the Windows API. Most Windows references use the word TYPE instead of the PureBasic's term of Structure, and UNION instead of PB's use of both Structure plus StructureUnion within that structure.
Here is the way the Win32.Hlp describes Small_Rect, which is a structure:
Code: Select all
typedef struct _SMALL_RECT { // srct
SHORT Left;
SHORT Top;
SHORT Right;
SHORT Bottom;
} SMALL_RECT;
But this brings up another problem, which is that PureBasic has a set of reserved words, and both Left() and Right() are functions in PureBasic. So does naming some fields in this structure the same way cause a problem? To some compilers, such as PowerBasic, it does, because keywords there are universally exclusive, meaning that the context of use ia not considered. Fortunately, this is not true of PureBasic. So no problem there.
The "typedef struc" is actually just "Structure" in Purebasic. the "//" just represents a ";", or comment in PureBasic syntax. The "}" (right curly bracket) near the bottom represents the "EndStructure" statement in PureBasic. So to convert the above into the equivalent format in PureBasic, you would end up with this:
Code: Select all
Structure SMALL_RECT ; srct
Left.w
Top.w
Right.w
Bottom.w
EndStructure
C and C++ are case-sensitive programming languages, and the underscore in front of the structure name is suppose to make it suitable for export. PowerBasic does not require the underscore, and names of variables, structures, and fields are case insensitive.
The really neat thing though, is that PureBasic does not require you to create this structure in your own code - you have access to it by virtue of the power of PureBasic to resolve references to structures defined by the Win32 API automatically. But understanding how C/C++ types convert to PureBasic syntax is necessary in order to make use of them and the fields that they represent.
has-been wanna-be (You may not agree with what I say, but it will make you think).
Next question is, how do you emulate a CallBack (or Hook) procedure in PureBasic? Some of the Windows API calls require that you pass the a procedure pointer to a procedure (in your own code or in a DLL) that it will call automatically, either with the requested information, or when some event transpires (takes place), depending upon the nature of the CallBack process.
CallBack procedures are crutial to handling real time events under Windows, such as processing Mouse movements and buttons, or keyboard presses. Yet at the same time, some part of the Windows API rely on CallBacks just to give you some information from the system, almost like a busy office assistant that tells you she will take care of your request when she finds the time, but she isn't going to do it at this very moment.
A CallBack procedure behaves rather like a WHEN statement. If you say, "When you get home, do your homework", you are defining a future event and what you want to happen when that event occurs. I've often thought that it would be so much easier for people to understand callbacks if they had resorted to a WHEN syntax instead.
A Hook procedure is the same thing. It invokes the image of baiting a fishhook and letting the line just dangle in the water. When a fish rises to the bait and bites, you just reel it in.
Anyway, to make a callback procedure work, it has to be exposed to the event mechanism, or more procisely, the system has to be informed that when the event, next takes place, to make a call to the procedure that has been esxposed to it. It is up to the procedure to then determine if it is to take any action, whether the message it received is intended for it, to forward the message if is not the recipient, to send other messages if so required, and to remove itself from the callback process once it has served its purpose.
I have so far found two references to using CallBack Procedures in PureBasic, but I rather hope someone with more experience will attempt to handle this complex subject.
CallBack procedures are crutial to handling real time events under Windows, such as processing Mouse movements and buttons, or keyboard presses. Yet at the same time, some part of the Windows API rely on CallBacks just to give you some information from the system, almost like a busy office assistant that tells you she will take care of your request when she finds the time, but she isn't going to do it at this very moment.
A CallBack procedure behaves rather like a WHEN statement. If you say, "When you get home, do your homework", you are defining a future event and what you want to happen when that event occurs. I've often thought that it would be so much easier for people to understand callbacks if they had resorted to a WHEN syntax instead.
A Hook procedure is the same thing. It invokes the image of baiting a fishhook and letting the line just dangle in the water. When a fish rises to the bait and bites, you just reel it in.
Anyway, to make a callback procedure work, it has to be exposed to the event mechanism, or more procisely, the system has to be informed that when the event, next takes place, to make a call to the procedure that has been esxposed to it. It is up to the procedure to then determine if it is to take any action, whether the message it received is intended for it, to forward the message if is not the recipient, to send other messages if so required, and to remove itself from the callback process once it has served its purpose.
I have so far found two references to using CallBack Procedures in PureBasic, but I rather hope someone with more experience will attempt to handle this complex subject.
has-been wanna-be (You may not agree with what I say, but it will make you think).
- netmaestro
- PureBasic Bullfrog
- Posts: 8433
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Here's an example of passing a procedure address to a WinApi function. It lists the names of all open windows on your system:
Code: Select all
Procedure GetAllWindows(hWnd, lparam)
name.s = Space(100)
GetWindowText_(hWnd, @name, 100)
If Not name
name = "Not Named"
EndIf
Debug Str(hWnd) + ": " + name
ProcedureReturn #True
EndProcedure
EnumWindows_(@GetAllWindows(), 0)
BERESHEIT
Another issue with Windows API calls is that often, you must supply a string to receive a result. All strings with Windows API use are null-terminated, which is native to C/C++ and PureBasic. An equivalent type with PowerBasic is the ASCIIZ string. However, when you call a Windows API and a string (or buffer) has to receive the result, you must first create a string of sufficient length to receive any possible response, and it must allow a final character of #Null (Chr(0)) value. There are several ways to create an area in memory sufficiently large to receive a returned string, and the called API will conveniently place a #Null character at the end of any valid return.
A common way is to do something like this:
or like this:
Note that the PureBasic Help file give the correct syntax for the second method, but that it may not be clear that the curly brackets are part of the syntax used.
You can also create a Byte array and pass a pointer reference to it, or use AllocateMemory() to set aside an area of memory to receive the returned characters. There is no one right way to do these things, but there can be some performance and convenience or available function issues involved. The problem with Null-terminated strings is that in some cases, particularly when handling data from non-text files, bytes with a zero value are common. The best course then is to use AllocateMemory() and manage that content via memory references, since this method does not assume that the content represents null-terminated strings.
A common way is to do something like this:
Code: Select all
somestr.s=Space(256)
Code: Select all
Define somestr.s{257}
You can also create a Byte array and pass a pointer reference to it, or use AllocateMemory() to set aside an area of memory to receive the returned characters. There is no one right way to do these things, but there can be some performance and convenience or available function issues involved. The problem with Null-terminated strings is that in some cases, particularly when handling data from non-text files, bytes with a zero value are common. The best course then is to use AllocateMemory() and manage that content via memory references, since this method does not assume that the content represents null-terminated strings.
has-been wanna-be (You may not agree with what I say, but it will make you think).
Console Screen Reflects Screen Size
When you work with the Console, the current screen resolution determines much of what you get as a result. With higher resolutions, the letters that appear on the console are smaller, and you can display more characters per line and more rows when the console window is maximized.
GetSystemMetrics_() can be used to determine what the current screen resolution is, and GetLargestConsoleWindowSize() can be used to determine
the maximum number of lines and rows that can be viewed when the console window is set to its largest size. The console Screen Buffer can be made much larger if you want, in which case the displayed console window will automatically add vertical and horizontal scroll bars as needed.
An even more versitile set of API calls can be found with GetConsoleSystemBufferInfo_() and SetConsoleSystemBufferInfo_(), both of which make use of a structure called ConsoleScreenBufferInfo. This structure can be used to identify or controll the console screen, character
color, and the size of the console screen buffer.
If you make your own grapics window, setting the font, size, and color are easily done. That means you exercise enough control over the console so as to maintain the same appearance, regardless of screen resolution.
If you have Windows XP or Vista, there are some additonal Console commands provided that are not found in some of the earlier windows versions. These are documented on Microsoft's web site, but may limit your ability to distribute your programs. Though I've not explored these added API calls, some of them do deal with Console Fonts.
There are at least two PureBasic libraries released that give you some alternatives for the Console. One is called ConsoleX and the other is called ConsoleEX. You can find these and other libraries for PureBasic at this link: http://www.purearea.net/pb/english/userlibs.php
GetSystemMetrics_() can be used to determine what the current screen resolution is, and GetLargestConsoleWindowSize() can be used to determine
the maximum number of lines and rows that can be viewed when the console window is set to its largest size. The console Screen Buffer can be made much larger if you want, in which case the displayed console window will automatically add vertical and horizontal scroll bars as needed.
An even more versitile set of API calls can be found with GetConsoleSystemBufferInfo_() and SetConsoleSystemBufferInfo_(), both of which make use of a structure called ConsoleScreenBufferInfo. This structure can be used to identify or controll the console screen, character
color, and the size of the console screen buffer.
If you make your own grapics window, setting the font, size, and color are easily done. That means you exercise enough control over the console so as to maintain the same appearance, regardless of screen resolution.
If you have Windows XP or Vista, there are some additonal Console commands provided that are not found in some of the earlier windows versions. These are documented on Microsoft's web site, but may limit your ability to distribute your programs. Though I've not explored these added API calls, some of them do deal with Console Fonts.
There are at least two PureBasic libraries released that give you some alternatives for the Console. One is called ConsoleX and the other is called ConsoleEX. You can find these and other libraries for PureBasic at this link: http://www.purearea.net/pb/english/userlibs.php
has-been wanna-be (You may not agree with what I say, but it will make you think).
Re: Windows Programming: Learning more about the Win32® API.
Sorry for my english ! (Windows Xp, Vista and Windows 7, Windows 10)
Re: Windows Programming: Learning more about the Win32® API.
Keep 'm rolling, people, good stuff to nick and abuse in the guide...
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
( The path to enlightenment and the PureBasic Survival Guide right here... )