Day 045 - A DbgView digression
With my memory refreshed on WinDev's testing capabilities, I created a test class as follows:
MyClass is class END PROCEDURE Constructor() PROCEDURE Destructor() PROCEDURE MethodA(intValue is int) RESULT intValue PROCEDURE MethodA(strValue is string) RESULT strValue PROCEDURE MethodB(value) RESULT value
I started with MethodB, which takes a parameter of undefined type.Â
Here's my test data - the first iteration passes a number, the second a string.
In both cases I get back the expected value, but am I really passing a string? I hadn't put it in quotes. I tried setting a breakpoint in the class, but the break point never triggered.Â
So I thought I'd do what I often do in Clarion when I can't rely on the debugger: use OutputDebugString. This is a Windows API call that writes a string to the system log, which you can view with the DbgView utility.Â
But how to call OutputDebugString?
It turns out there's a utility program included with WinDev called WDAPI, and it will write the WinDev code you need for various API calls:
The code I needed was:
lpOutputString is int système // C Type:LPCSTR, is a string address, you can also specify a string directly API("KERNEL32","OutputDebugStringA",lpOutputString)
but it would be silly to add that to every method. Much easier to create a global procedure, right?Â
In the project explorer I found the Procedures node and right-clicked. I got options to create a subfolder and create a global procedure set. The latter seemed like it would get me a little closer;Â I guess a procedure set is a way of grouping global procedures. But how to create the procedure?
I found that option on the main menu under Insert. But nothing happened when I exercised that menu option. I was still in the procedure set with no procedure.Â
So I closed the procedure set without saving and then I tried again, this time without creating the procedure set first. I got a window to save a new procedure set:
and then a prompt asking me for the name of my procedure, which I called Debug. When I saved I got the procedure declaration, and I pasted in the code from WDAPI:
Â
As you can see I had a syntax error, which I wasn't sure how to handle.Â
But first I updated my MethodB code to call Debug():
PROCEDURE MethodB(value) Debug(value) RESULT value
The help seemed to indicate that I could specify a string directly instead of using the suspect definition for a long pointer. That didn't seem right to me, first because sMsg is a WinDev string and second because the API call really is expecting a pointer. But what the heck - maybe WinDev was working some magic with the API call. So I tried:
PROCEDURE Debug(sMsg is string) // lpOutputString is int système // C Type:LPCSTR, is a string address, you can also specify a string directly API("KERNEL32","OutputDebugStringA",sMsg)
but that crashed the test. So I declared the pointer this way:
nLpOutputString is system int
and then I dug around until I discovered that the address operator is the ampersand. So I assigned the string address
nLpOutputString = &sMsg
which compiled fine. When I ran the test, however, I got a runtime error on the API call and the test failed.Â
Clearly I needed to find a way to change my string to a cstring and feed the cstring pointer to the API call.Â
Eventually I came across a page that indicated I needed to use the ASCIIZ string type in this situation. Only one problem: there is no ASCIIZ string type in WinDev 17, at least not that I can see. But there is an ANSI string type.Â
Here's the code I ended up using:
PROCEDURE Debug(sMsg is string) nLpOutputString is system int// C Type:LPCSTR, is a string address, you can also specify a string directly sDebugMsg is ANSI string sDebugMsg = sMsg nLpOutputString = &sDebugMsg API("KERNEL32","OutputDebugStringA",nLpOutputString)
Now my unit test ran, and more importantly I could see the log statements in DbgView's window.Â
[4520] abc [4520] 35
And I was out of time. More tomorrow!Â
Â
Â
Â