1) Len(CStr(Num)) <-- Is the CStr function really necessary ? The code seems to run without an error even without the convert to string function.
Can you explain the rationale of why you used the function ?
2) Below is how i would code to change the view to a calculator view.
3) In your opinion, is it better to use hex for large numbers because it would take less digits than in decimal?
1) The vba
Len function returns the number of characters of the string that is passed to it. However, if the function is not passed a string, it behaves differently and instead of returning the number of characters it returns the number of Bytes of the variable passed to it.
Try passing 123 instead of 1234 and it will error out at the MID function call because in this case, the Len function returns 6 (bytes) instead of 3 (Characters)
The reason 1234 didn't cause an error is pure coincidence: Number of characters =4 and number of bytes is 4 (Long Variable)
By coercing the Num variable into a String using CStr, the Len function returns the number of characters in the Num Variable rather than the number of bytes in the Num Varaible.
Take a look at the
Len function documentation:
Len function (Visual Basic for Applications)
2) AFAIK, a server application can be accessed and automated by client applications in 3 ways (Each to a different extent).
a- OLE Automation like when controling WinWord from Excel via WinWord Object Model. (Gives almost full control)
b- API calls like what we have done here (Gives much less control than OLE automation and relies on window handles which is not always possible as many controls are window-less controls and\or don't have a hwnd, ID or Text)
c- MSAA and IUIAutomation (Again, much less control than OLE Automation plus not all server applications provide these two interfaces)
In the case of Calc.exe, OLE automation is not possible.
What you can do with API calls is limited (Calc.exe menus have no HWND or IDs so you can't activate them with API calls )
As for MSAA and IUIAutomation, Calce.exe Menu items are accessible but for some obscure reason their
AccDoDefault Method (to actually activate them) is not available.
So, in short, you can't reliably activate Calc.exe menus with any of the above mentioned methods and you are left with the unreliable
SendKeys option or with sending shaky API mouse clicks.
3)
&H is just an hexadecimal represention of a number. Internally, whether you write &H1 or 1 it is the same for the compiler.
The reason you see a lot of hexadecimal in API programming, is because APIs are written in the C langauge which, unlike VB, supports memory pointers and can natively access and manage memory locations.
Hexadecimal representations are just a convinient way for the programmer to visualize memory in terms of Byte sequences..
When programming with Windows APIs, sooner or later, you will face a situation where you need to read some memory locations.
For example say an API function returns an integer value in of one of its arguments. Let's assume this integer value is in a variable called
lParam .
lParam is an integer which is 2 Bytes or 16 bits of sequenced memory . Now suppose the first and second bytes each contain a byte value that we need in our code.
If we use hexadecimal to represent the value in lParam, the programmer can more easily visualize its contenets byte by byte.
Suppose lParam contains the integer value : 8069
The Hex representation of the Decimal 8069 is
1F 85. (High Byte = 1F, Low Byte = 85)
As you can see, it is now clearer to see what's going on in each Byte of the memory occupied by lParam and we now know the Byte values that we need in our code.
To extract, in code, the low order and High order Bytes of the lParam Integer, we can use 3 different ways :
BitMasking,
RtlMoveMemory or
LSet
Here is an example that shows how to extract (using the 3 methods) the lower and higher Bytes of the integer value : 8069
VBA Code:
Option Explicit
Type MyInteger
intValue As Integer
End Type
Type MyIntegerBytes
LowOrder As Byte
HighOrder As Byte
End Type
#If VBA7 Then
Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#Else
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
#End If
Sub example()
Dim intVar As Integer
intVar = 8069 '<== &H1F85
Debug.Print Hex(intVar) & " Hex" & " =" & intVar & " Dec"
Debug.Print "*****************************************"
Debug.Print "Extract Low and High Bytes of " & Hex(intVar)
Debug.Print "*****************************************"
Debug.Print "Using BitMask "
Debug.Print Space(10) & Hex(intVar And &HFF) & vbTab & "LoByte" ' extract low order Byte
Debug.Print Space(10) & Hex(((intVar And &HFF00) \ &H100) And &HFF) & vbTab & "HiByte" ' extract high order Byte
Debug.Print "*****************************************"
Debug.Print "Using RtlMoveMemory API "
Dim LowOrder As Byte, HighOrder As Byte
CopyMemory LowOrder, intVar, 1 ' extract low order Byte
CopyMemory HighOrder, ByVal VarPtr(intVar) + 1, 1 ' extract high order Byte
Debug.Print Space(10) & Hex(LowOrder) & vbTab & "LoByte"
Debug.Print Space(10) & Hex(HighOrder) & vbTab & "HiByte"
Debug.Print "*****************************************"
Debug.Print "Using LSet "
Dim tMyInteger As MyInteger, tMyIntegerBytes As MyIntegerBytes
tMyInteger.intValue = intVar
LSet tMyIntegerBytes = tMyInteger
Debug.Print Space(10) & Hex(tMyIntegerBytes.LowOrder) & vbTab & "LoByte" ' extract low order Byte
Debug.Print Space(10) & Hex(tMyIntegerBytes.HighOrder) & vbTab & "HiByte" ' extract high order Byte
End Sub
This all looks rather daunting but with practice it becomes a bit clearer. I myself still don't fully understand many aspects of API programming despite the fact that I have been making use of a lot of APIs in my vba codes but I keep studying and trying.
If you are intersted in learning about this API programming stuff , I suggest that you start by learning the basics of binary and Hex arithmetic. There is plenty of material on the subject in the internet.
Good luck.