Powerbasic Museum 2020-B

IT-Consultant: Patrice Terrier => Addon tools for PB => Topic started by: Patrice Terrier on April 05, 2009, 12:43:44 PM

Title: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on April 05, 2009, 12:43:44 PM
zTrace 1.52

Is a small Win32 SDK DLL to display debugging information into a popup window tool, and/or a text file.
zTrace uses a distinct thread to work in parallel of the current application you want to debug.

zTrace is very useful at development time to check whether a program operates properly, it has been modeled onto the WinDev's Trace API.

Declaration:
DECLARE FUNCTION zTrace LIB "zTrace.DLL" ALIAS "zTrace" (zMessage AS ASCIIZ) AS LONG
DECLARE FUNCTION zDebug LIB "zTrace.DLL" ALIAS "zDebug" (zMessage AS ASCIIZ) AS LONG

Syntax to use:
zTrace("StringInformation")
zDebug("StringInformation")

Parameter detail:
QuoteStringInformation, holds the information that will be displayed in the Trace window.

Trace Window:

QuoteStringInformation, holds the information that will be stored in the zDebug.txt file.

zDebug.txt report:


Contextual popup menu (right mouse click on the trace window):

Screen shot:
(http://www.zapsolution.com/pictures/zDebug.jpg)

This utility is freeware, not public domain. This means that you can use it for your own purposes, even in commercial applications, without paying a fee, but not to make derivative works from, sell or redistribute without permission. Also you must assume the entire risk of using it. Downloading the software indicates that you accept these terms.

PS: zTrace is another example of what could be done only with the plain low level Win32 SDK flat API.

...
Title: zTrace.zip is available for download!
Post by: Patrice Terrier on April 05, 2009, 07:05:20 PM
zTrace.zip is attached to the first post of this thread.

Thank you to report any problem you may encounter with it.

...

Title: zTrace 1.0 (Insights)
Post by: Patrice Terrier on April 06, 2009, 10:09:00 AM
Here are a few insights about zTrace.

1 - The message pump:

WHILE GetMessage(Msg, %NULL, 0, 0)
   '// Easier to detect the right mouse button click on the listBox from the message pump
   IF Msg.hWnd = hCtrl AND Msg.Message = %WM_RBUTTONDOWN THEN
      CALL ToolProc(hWnd, %WM_RBUTTONDOWN, 0, 0)
   ELSE
      IF IsDialogMessage(hWnd, Msg) = %FALSE THEN
         CALL TranslateMessage(Msg)
         CALL DispatchMessage(Msg)
      END IF
   END IF
WEND

And the masterpiece is this
QuoteIF Msg.hWnd = hCtrl AND Msg.Message = %WM_RBUTTONDOWN THEN
   CALL ToolProc(hWnd, %WM_RBUTTONDOWN, 0, 0)
ELSE
It is the easiest way to detect the right mouse button click onto the listBox to popup the contextual menu.


2 - The CASE %WM_DESTROY:
While %WM_DESTROY is being called when you click on the close button of the tool window.
It is never called when zTrace shuts down after the closing of the main debugged application,
the solution is to clear and save the zTrace parameters from DllMain:

    IF Reason = %DLL_PROCESS_DETACH THEN
       IF gnBackBrush THEN
          CALL DeleteObject(gnBackBrush): gnBackBrush = 0
          CALL zLoadSaveCoordinates (gnX, gnY, gnW, gnH, 1)
       END IF
    END IF



3 - Save settings:
This code is responsible to save/restore the settings from the registry

SUB zLoadSaveCoordinates (BYREF x AS LONG, BYREF y AS LONG, BYREF w AS LONG, BYREF h AS LONG, BYVAL RW AS LONG)
    STATIC WasCoordinates AS STRING
    IF RW THEN '// Save settings
       WasCoordinates = LTRIM$(STR$(x)) + "," + LTRIM$(STR$(y)) + "," + LTRIM$(STR$(w)) + "," + LTRIM$(STR$(h)) + "," + LTRIM$(STR$(gbUseTopMost)) + "," + LTRIM$(STR$(gbSaveCoordinates))
       IF LEN(WasCoordinates) THEN CALL zSetReg(%HKEY_LOCAL_MACHINE, $RegistryKey, $RegistryCoordinates, (WasCoordinates))
    ELSE '// Restore settings
       IF LEN(WasCoordinates) = 0 THEN
          WasCoordinates = zGetReg(%HKEY_LOCAL_MACHINE, $RegistryKey, $RegistryCoordinates)
          x = VAL(PARSE$(WasCoordinates, 1))
          y = VAL(PARSE$(WasCoordinates, 2))
          w = VAL(PARSE$(WasCoordinates, 3))
          h = VAL(PARSE$(WasCoordinates, 4))
          gbUseTopMost       = VAL(PARSE$(WasCoordinates, 5))
          gbSaveCoordinates  = VAL(PARSE$(WasCoordinates, 6)): IF gbSaveCoordinates = 0 THEN w = 0
       END IF
       IF w = 0 OR h = 0 THEN w = %MIN_WIDTH: h = %MIN_HEIGHT: x = 0: y = 0
    END IF
END SUB


...
Title: Re: zTrace 1.0 (debugging utility)
Post by: Dominique Bodin on April 06, 2009, 03:07:53 PM
Thank's Patrice.

could you add to the zTrace tool the ability to print the windows content ?
It would be better than to have to copy the content and paste in an editor
to finaly print it . . .

Thank's

Dominique
Title: Re: zTrace 1.0 (debugging utility)
Post by: Patrice Terrier on April 06, 2009, 08:55:11 PM
Dominique

You can do the same than the code below that copy to clipboard


        CASE %IDM_CopyToClipboard
             hCtrl = GetDlgItem(hWnd, %ID_LISTBOX)
             nCount = SendMessage(hCtrl, %LB_GETCOUNT, 0, 0)
             IF nCount > 0 THEN
                sBuffer = ""
                FOR K = 0 TO nCount - 1
                    sBuffer = sBuffer + zGetTextListbox(hCtrl, K) + $CRLF
                NEXT

'               CLIPBOARD SET TEXT sBuffer '// requires PB 9.0+
                LOCAL hClipData, hGlob AS DWORD
                hClipData = GlobalAlloc(%GMEM_MOVEABLE OR %GMEM_DDESHARE, LEN(sBuffer) + 1)
                hGlob = GlobalLock(hClipData)
                POKE$ hGlob, sBuffer + CHR$(0)
                CALL GlobalUnlock(hClipData)
                IF OpenClipboard(0) THEN
                   CALL EmptyClipboard()
                   CALL SetClipboardData(%CF_TEXT, hClipData)
                   CALL CloseClipboard()
                ELSE
                   CALL GlobalFree(hClipData)
                END IF

            END IF


and instead of sending to clipboard then send it to printer using XPRINT.

I shall update the zip file with the clipboard feature for the next version.

...
Title: zTrace (updated to version 1.01)
Post by: Patrice Terrier on April 07, 2009, 10:51:30 AM
Under request of Dominique Bodin,

i have added two new options:
The new zip file is attached to the first post of this thread.

...
Title: Re: zTrace 1.01 (debugging utility)
Post by: Eddy Van Esch on April 07, 2009, 11:44:52 AM
Patrice,

Nice tool, thanks !
I sometimes have to show (very) large strings while debugging, so I took the liberty of adding a horizontal scrollbar to zTraces listbox.
Modifications shown in bold:
Quote
          hCtrl = CreateWindowEx(0, "ListBox", BYVAL %NULL, _
                                 %WS_CHILD OR %WS_VISIBLE OR %WS_VSCROLL OR %WS_HSCROLL OR %LBS_MULTIPLESEL OR _
                                 %LBS_HASSTRINGS OR %LBS_NOINTEGRALHEIGHT OR %LBS_EXTENDEDSEL OR _
                                 %LBS_DISABLENOSCROLL, _
                                 0, 0, UseW, UseH, _
                                 hWnd, %ID_LISTBOX, zInstance(), BYVAL %NULL)
          CALL SENDMESSAGE(hCtrl, %LB_SETHORIZONTALEXTENT, 6000, 0)  '<-- change scrollwidth here if necessary

Kind regards
Eddy
www.devotechs.com (http://www.devotechs.com) -- HIME Huge Integer Math and Encryption library--
Title: Re: zTrace 1.01 (debugging utility)
Post by: Patrice Terrier on April 07, 2009, 12:42:08 PM
Eddy,

Thank you for the feedback, i think showing the horizontal srollbar could become another option of the popup menu.

...
Title: Re: zTrace (updated to version 1.02)
Post by: Patrice Terrier on April 07, 2009, 06:18:51 PM
Under request of Eddy Van Esch,

i have added a new option:
It can be turned On/Off on the fly.

The new zip file is attached to the first post of this thread.

...
Title: zTrace 1.02 (No news, good news)
Post by: Patrice Terrier on April 09, 2009, 05:33:11 PM
Because no problem was reported, i shall consider that zTrace is working well 8)

...
Title: Re: zTrace 1.02 (debugging utility)
Post by: Paul Squires on April 09, 2009, 10:48:58 PM
I have been using it since the day that you posted it.

I love it.   :)

No problems to report from me. I will post if something comes up.

Title: Re: zTrace 1.02 (debugging utility)
Post by: Patrice Terrier on April 09, 2009, 10:51:44 PM
Thank you Paul.

...
Title: Re: zTrace 1.02 (debugging utility)
Post by: Eddy Van Esch on April 10, 2009, 12:20:42 AM
Patrice,

You know, the danger in publishing a tool like zTrace is that everyone keeps asking for more and more features ... ;D
Speaking about new features ... ;)

Before you published zTrace, I was using a console window (from PBWin) to print text to.
I used that console window often to test algorithms in a small test program without any GUI at all. The console window was the 'GUI'.
At the end of the test code, I place a SLEEP xxx statement to halt the program and to enable me to study the programs output in the console window.

The nice thing of using a console window as output, is that, by closing the console window (clicking the "X") the entire program is terminated. So no need to foresee any code in the test program to properly shut it down. Just clicking the X closes down the program.
The difference with zTrace is that, when I close the zTrace window, the main calling program continues to run.
In some cases, this might be the desired situation, but usually in my case, I prefer that the calling program is terminated along with the debug window.

This is probably asking much, but any chance of implementing this in zTrace ....?   :-\

Kind regards
www.devotechs.com (http://www.devotechs.com) -- HIME Huge Integer Math and Encryption library--
Title: Re: zTrace 1.02 (debugging utility)
Post by: Patrice Terrier on April 10, 2009, 05:51:48 AM
In such a case, DestroyWindow(hParent), should do it.

However zTrace is not of much interrest for a console window, because you can use "?" already ...
Title: Re: zTrace 1.02 (debugging utility)
Post by: Eddy Van Esch on May 06, 2009, 10:43:52 PM
Hi Patrice,

Is it too late to make another feature request ?   :)

When printing a lot of data to the zTrace window, the text disappears on the bottom of the zTrace window.
To view the text that is added when the window is 'full', you have to use the vertical scrollbar to scroll downward to see the text.

Would it be possible to make zTrace scroll the text automatically upwards so that the text that was printed last is always visible ?
This feature would be most helpful to me.

Kind regards
Eddy
Title: Re: zTrace 1.02 (debugging utility)
Post by: Patrice Terrier on May 06, 2009, 11:02:41 PM
I did it already!
(because i had the same need myself)

But i didn't took the time to post it there, i shall do it tomorrow  8)

...

Title: Re: zTrace 1.02 (debugging utility)
Post by: Eddy Van Esch on May 06, 2009, 11:14:08 PM
Splendid, Patrice !!   :)
Thanks a lot !

Kind regards
Eddy
Title: Re: zTrace 1.52 (debugging utility)
Post by: Eddy Van Esch on May 07, 2009, 09:19:07 AM
Thanks again, Patrice !!

Kind regards
Eddy
Title: Re: zTrace 1.52 (debugging utility)
Post by: Dominique Bodin on May 07, 2009, 08:40:18 PM
Thank's a lot patrice.

I see the .bas isn't updated in the first post .zip . . .
Thank's

Dominique
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on May 07, 2009, 09:53:00 PM
Ok  :)

...
Title: Re: zTrace 1.52 (debugging utility)
Post by: Dominique Bodin on May 07, 2009, 10:06:30 PM
Thank's patrice
Title: Re: zTrace 1.52 (debugging utility)
Post by: Eddy Van Esch on June 17, 2009, 12:04:44 PM
If you would like to change the background color of zTrace, make following changes to the source code:

Add the line in bold:
Quote#COMPILE DLL "zTrace.dll"

#INCLUDE "WIN32API.INC"

'----------------------------------------------------------------------
%zTrace_BGColor = &HF4F4F4   'zTrace background color
%dwStyle = %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN OR %WS_CAPTION OR %WS_SYSMENU OR %WS_THICKFRAME


Change the bold parts:

QuoteCASE %WM_CREATE
        'A good place to initiate things, declare variables,
        'create controls and read/set settings from a file, etc.
        '-------------------------------------------------------
         IF gnBackBrush = 0 THEN gnBackBrush = CREATESOLIDBRUSH(%zTrace_BGColor)

Quote
    CASE %WM_CTLCOLORBTN, %WM_CTLCOLOREDIT, %WM_CTLCOLORLISTBOX, %WM_CTLCOLORSTATIC
         ' wParam is handle of control's display context (hDC)
         ' lParam is handle of control
         '------------------------------------------------------
         IF lParam = GetDlgItem(hWnd, %ID_LISTBOX) THEN
            CALL SETBKCOLOR(wParam, %zTrace_BGColor)

PS. I had to use 'quote' instead of 'code' or I could not indicate the text in bold in the code ...  :)

Kind regards
Eddy

Title: Re: zTrace 1.52 (debugging utility)
Post by: Jim Padgett on December 30, 2010, 03:29:40 PM
Is ztrace thread safe ?
If I ztrace "This is from thread " & Str$(x)  from my thread function
Where x = long value passed to the thread from my  main app ..

Will this simply add another line to ztrace output from the ztrace window previously opened ?

Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on December 30, 2010, 03:57:40 PM
QuoteWill this simply add another line to ztrace output from the ztrace window previously opened ?

Yes.

...
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on August 07, 2011, 06:10:35 PM
The first post of this thread has been updated, to fix the ZIP file corruption caused by the "Server Collapse".

...
Title: Re: zTrace 1.52 (debugging utility)
Post by: Paul Elliott on April 07, 2012, 05:02:14 PM
Patrice,

Thanks for making such a useful tool.

But I'm having problems with zTrace.
I'm running a PB CC v6.03 program that is reading all the normal INC files and capturing certain
bits of information. Normally I'm displaying on the console the files as I process them but needed
a bit more information under strange conditions ( strange based on what I'm trying to capture ...
but the file processing is fairly straight open /read/close ).
So I saw your tool and thought that it would solve my problem and it does the first time thru.
But if when my program is about to end and it's waiting for me to press a key, I change to your
window and select create zDebug output then you create the file. But if I run my program again
and your program reads the ztrace.cfg and sets the option to create the zDebug output, after
22 lines to your window my program aborts and Windows wants to run it thru a debugger.
On the run that works there are around 2000 lines in the zdebug.txt file.

I'm running on Windows XP SP3 with MS Security Essentials  with 2 gig ram.
My program has no Threads but does have up to 10 files open at once but they are all closed
before my program ends.

Do you know of anything that could be causing this?
Any suggestions for debugging it? Can I copy most of the source ( minus the DLL main stuff ) into
my CC program and compile it?

Title: Re: zTrace 1.52 (debugging utility)
Post by: Paul Elliott on April 07, 2012, 06:37:16 PM
Well, it wouldn't compile including most of the zTrace.bas ( minus the dll main ).
Had to add a few variables that were missed ( am using #DIM ALL ). Even tried compiling
the DLL with Win v10.03. Then trying adding #Option AnsiAPI. No difference.

I'll just delete the CFG file and set the Debug save option right before ending my program.
It is a great tool and works for what I need ( with just a little tweaking ).

Title: Re: zTrace 1.52 (debugging utility)
Post by: Paul Elliott on April 07, 2012, 07:37:13 PM
Could there be some conflict/overlap between CreateFile and PB's FreeFile?

In the main program, I keep opening (based on PB's FreeFile ) & closing files ( eventually but
they may be nested up to 9 levels ). the next file opened is based on PB's FreeFile.

The names will not overlap between main program & DLL but is it possible the underlaying
handle may get closed? If this is possible, how would I check for a handle already in use?

Title: Re: zTrace 1.52 (debugging utility)
Post by: Paul Elliott on April 07, 2012, 08:43:57 PM
Ended up putting a temporary change in ( until the real reason is found ).

Zeroed gbDebug when it is read in.
In zTrace check for "*CLOSE*IT*" as input string and do the checks/loop to output the
whole listbox and close the file. I send this after I have closed all my files and right before
waiting for a keystroke.

Seems to work for me. Now on to fixing more of my other problems.

Title: Re: zTrace 1.52 (debugging utility)
Post by: John Aadnoey on October 29, 2013, 02:13:13 AM
Thanks for this program. I'm definatlly gonna use it as I develop my own software.

Great stuff, Patrice
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on October 29, 2013, 04:48:46 AM
John Aadnoey

That was the first code i ported to 64-bit, because i couldn't develop anymore without it  :)
Title: Re: zTrace 1.52 (debugging utility)
Post by: Norbert Spoerl on November 07, 2013, 12:21:00 PM
Hello Patrice,

yesterday I made a download for your zTrace 1.52.

Now a question. Can I use that inside a PB-DLL-Code?

Inside a PB-Exe-Sourcecode, it was okay. In a DLL I got an axception error.

Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on November 07, 2013, 01:43:29 PM
To be used from inside DLL(s) was the main purpose of it  :)

But perhaps you are using it within a critical section.
And without seeing the code it is hard to say.
Also the PB version uses ASCIIZ (char), while the C++ 32/64-bit uses UNICODE (wchar).
Title: Re: zTrace 1.52 (debugging utility)
Post by: Norbert Spoerl on November 12, 2013, 10:39:52 AM
Hi Patric,

I think the reason for the error by using zTrace inside DLL-code was the point, that the EXE is not native code. The EXE goes with a runtime library. With an PB-EXE the error is not repeatable.

So far I have used a solution of MCM -> STDOUT to a console window. Understand I zTrace right, that it is practically the same, only with more comfort?
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on November 12, 2013, 11:05:11 AM
Quotethe EXE is not native code. The EXE goes with a runtime library

I do not understand, what runtime are you speaking about  ::)
Title: Re: zTrace 1.52 (debugging utility)
Post by: Norbert Spoerl on November 12, 2013, 11:25:27 AM
This is an EXE that was build with a programming language named PROFAN. A part of the PROFAN EXE is a runtime.
http://xprofan.de/start.htm (http://xprofan.de/start.htm)
Title: Re: zTrace 1.52 (debugging utility)
Post by: John Aadnoey on December 21, 2013, 10:08:00 AM
Quote from: Patrice Terrier on October 29, 2013, 04:48:46 AM
John Aadnoey

That was the first code i ported to 64-bit, because i couldn't develop anymore without it  :)

I can understand why.

On the PB version; why is it using aschiiz and not string? any advantage to asciiz over string?
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on December 21, 2013, 10:26:08 AM
QuoteOn the PB version; why is it using asciiz and not string? any advantage to asciiz over string?

The answer is obvious: i am using this 32-bit version with several languages, not just PB  :)
Title: Re: zTrace 1.52 (debugging utility)
Post by: José Roca on December 21, 2013, 01:03:40 PM
Use BYCOPY, i.e. zTrace(BYCOPY DumpInfo), instead of zTrace(DumpInfo).
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on December 21, 2013, 02:41:30 PM
or like this zTrace((PBstring))
that is a short cut for BYCOPY.
Title: Re: zTrace 1.52 (debugging utility)
Post by: José Roca on December 21, 2013, 02:57:27 PM
I prefer to use the verbose way. It adds clarity. I even use BYREF in the parameters of my declares to be sure that this is what it's intended and not an omission.
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on December 21, 2013, 04:53:50 PM
I remember that Bob Zale had the project to remove the () short cut, but since his passing it is safe to use it.
Because i can't see who could change this :)
Title: Re: zTrace 1.52 (debugging utility)
Post by: John Aadnoey on December 23, 2013, 02:52:06 PM
I'm with Jose on the bycopy rather than (()) and byref over undefined. Way easier for us newbies to understand.
Anyway, I load up zTrace from a DLL in my program. And when my program ends, the zTrace DLL is still running, thereby crashing the VB6 IDE. (I Run it inside the IDE rather than compiling it).
My DLL is written in Powerbasic.
Any idea why?
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on December 23, 2013, 03:58:07 PM
I am not a VB6 user, thus i can't say.

zTrace has been designed to work from a DLL, not to be embedded in your source code.

However if the source code of zTrace doesn't match your level of expectations, feel free to edit it, to let it work the way you want, using basic string rather than ASCIIZ.

You can also write a helper function, just like what i did for the C++ version, to use wstring rather than WCHAR.
Title: Re: zTrace 1.52 (debugging utility)
Post by: John Aadnoey on December 23, 2013, 04:02:38 PM
Its not embedded in my code. I let my DLL load it.
To me it looks like zTrace is waiting for VB6 to shutdown, not the DLL. (because shutting down the VB6 IDE kills it)

"However if the source code of zTrace doesn't match your level of expectations"

Its definitely up to my expectations. have no doubt about that, I'm just trying to find out why the DLL ain't closing
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on December 23, 2013, 04:24:52 PM
Again, i have absolutly no knowledge of VB.

Did you try it without the VB6 IDE, i mean as a real standalone EXE ?
Title: Re: zTrace 1.52 (debugging utility)
Post by: John Aadnoey on December 23, 2013, 04:40:36 PM
Yes just three minutes ago. And then when I run the compiled VB6 code, It shut down as expected.

I wouldn't be surprised if its VB not shutting down the DLL beacuse the DLL has an open window. If window is closed before DLL gets shut down, it'll probably work.
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on December 23, 2013, 05:49:04 PM
Then this means that when you run it within the VB6 IDE, it runs as p-code not native code, that's it.

...
Title: Re: zTrace 1.52 (debugging utility)
Post by: John Aadnoey on December 23, 2013, 07:56:53 PM
Found out some more. When I run it in p-Native/VB6 IDE, if;
DLL opens a DialogWindow, program closes = crash
DLL opens a DialogWindow, DLL close DialogWindow, program closes = OK

Probably a VB6 bug/feature.
Title: Re: zTrace 1.52 (debugging utility)
Post by: Norbert Spoerl on December 24, 2013, 09:46:39 AM
Hi John,

zTrace is only useable with EXE/DLL of pure native Code. Please see my replys 34 and 36. I made the same experiences with another programming language.
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on December 24, 2013, 11:29:58 AM
zTrace is using GetModuleHandle("") to retrieve the instance handle, but in case of a run-time this is of course the handle of the run-time!
Title: Re: zTrace 1.52 (debugging utility)
Post by: John Aadnoey on December 24, 2013, 01:42:09 PM
Ah oki. That explains it. Then I'll just keep on using it on my pure PB hobby projects.

Thanks all
Title: Re: zTrace 1.52 (debugging utility)
Post by: Norm Cook on March 26, 2014, 02:38:08 PM
Patrice, late to the party, just stumbled onto this.  Thanks so much for sharing this
excellent debugging tool.  Here's a little routine I've been using to make coding/debugging
a little easier.  I've thrown just about everything at it and it seems to work OK.

Sub DoTrace(ByVal Msg As Variant)
Local sz As AsciiZ * 1000
Select Case VariantVT(Msg)
  Case %VT_BStr
   sz = Variant$(Msg)
  Case %VT_R4, %VT_R8   'single, double
   sz = "#" & Format$(Round(Variant#(Msg), 4))
  Case Else
   sz = "#" & Format$(Variant#(Msg))
End Select
zTrace sz
End Sub
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on March 26, 2014, 04:48:44 PM
There is no need to use Variant nor Format$ (both are bloated :) ).

You can just use zTrace like this:

zTrace(STR$(Value))
or
zTrace("Value =" + STR$(Value))
and in case of STRING
zTrace((MyString$))
or
zTrace(A$+ B$ + STR$(12))
Title: Re: zTrace 1.52 (debugging utility)
Post by: George Bleck on May 02, 2017, 10:05:08 PM
I absolutely love having zTrace in my toolbox and wanted to give back a slight "helper" that I use with it.

#IF NOT %DEF( %zTrace )
    %zTrace = 0
#ENDIF

#IF %zTrace = 0
    MACRO zTrace = #UTILITY
    MACRO zDebug = #UTILITY
#ELSE
    DECLARE FUNCTION zTraceX LIB "zTrace.DLL" ALIAS "zTrace" ( zMessage AS ASCIIZ ) AS LONG
    DECLARE FUNCTION zDebugX LIB "zTrace.DLL" ALIAS "zDebug" ( zMessage AS ASCIIZ ) AS LONG
    #IF %zTrace > 0
        MACRO zTrace = zTraceX
        MACRO zDebug = zDebugX
    #ELSE
        MACRO zTrace = zDebugX
        MACRO zDebug = zDebugX
    #ENDIF
#ENDIF


This slight mod allows you to leave zTrace code in and never have to remove it.  PLUS it adds some flexibility to the output path.

This allows you to easily include copious real-time logging in your code as well as switch the output (or remove logging completely) with a single constant change.
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on May 03, 2017, 10:18:35 AM
George--

Thank you.

The current version of zTrace is able to write to zdebug.txt directly from the contextual popup menu.

PBwin 10, now doesn't compile unused code anymore.
Thus using explicit linking rather than implicit is another solution,
and this is what i am using with the 64-bit version (explicit call is the same for PB) :

long zTrace(IN WCHAR* sPtr) {
    long nRet = 0;
    static HMODULE hDll;
    if (hDll == 0) {
        if (sizeof(LONG_PTR) == 8) {
            hDll = LoadLibrary(L"zTrace64");
        }
        else {
            hDll = LoadLibrary(L"zTrace32");
        }
    }
    if (hDll) {
        long_proc(WCHAR*);
        static zProc hProc;
        if (hProc == 0) { hProc = (zProc)GetProcAddress(hDll, "zTrace"); }
        if (hProc) { nRet = hProc(sPtr); }
    }
    return nRet;
}


The C++ 64-bit DLL version is only 11 Kb in size, it can create ANSI or UNICODE debug file.
In case of ANSI, a UTF-8 BOM header is now being used
this version can be downloaded from www.codeproject.com or from my private forum www.objreader.com
https://www.codeproject.com/Articles/1183063/zTrace-for-bit-only

Title: Re: zTrace 1.52 (debugging utility)
Post by: James C. Fuller on May 03, 2017, 11:56:07 AM
Patrice,
  I reverted back to an older version.
The debug.txt output was persistent once set and I often parse the output so I don't want a BOM.

James
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on May 03, 2017, 02:13:53 PM
No, it is not, you just have to remember to uncheck the menu option, once you are done, if you don't want it for the next session.

Or feel free to customize the source code to match your preference ;)

...
Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on May 03, 2017, 08:12:24 PM
Emil

zTrace is totaly independent from the compiler, it is a standalone DLL.
It has been inspired by the WinDev Trace API.

...
Title: Re: zTrace32.dll v3
Post by: Marc Pons on August 11, 2017, 04:17:11 PM
Hello Patrice

I wanted to use your nice ztrace tool v3 with unicode on window 32

but i've found only the win 64

so i've adapted a litle your code to be able to compile with mingw  gcc or g++


//+--------------------------------------------------------------------------+
//|                                                                          |
//|                               zTrace 3.00                                |
//|                                                                          |
//|                      Win32 SDK debugging window DLL                      |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                                                                          |
//|                         Author Patrice TERRIER                           |
//|                                                                          |
//|                         copyright(c) 2009-2017                           |
//|                                                                          |
//|                Patrice Terrier http://www.zapsolution.com                |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                  Project started on : 04--2009 (MM-DD-YYYY)            |
//|                        Last revised : 04-27-2017 (MM-DD-YYYY)            |
//+--------------------------------------------------------------------------+

// link to gdi32  and comdlg32  libs with g++ compiler at least for win 32
// for win 64 probably same ?

#ifndef UNICODE
# define UNICODE
#endif

#include <windows.h>

#if defined(__MINGW32__) || defined(__MINGW64__)
# if defined(__MINGW64__)
#  define A_CAPTION   "zTrace 3.00 64-bit"
#  define WND_CAPTION   L"zTrace 3.00 64-bit"
# else
#  define A_CAPTION   "zTrace 3.00 32-bit"
#  define WND_CAPTION   L"zTrace 3.00 32-bit"
# endif
#endif

#define WND_Style   (WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME)
#define WND_ExStyle (WS_EX_TOOLWINDOW)

#define HORIZONTAL_EXTENT    6000  // Maximum value for the horizontal scrollbar
#define MIN_WIDTH            300   // default client width size
#define MIN_HEIGHT           65    // default client height size

#define ID_LISTBOX           1

#define IDM_About            101  // menu popup
#define IDM_Hscroll          103  // menu popup
#define IDM_Print            104  // menu popup
#define IDM_CopyToClipboard  105  // menu popup
#define IDM_ClearContent     106  // menu popup
#define IDM_TopMost          107  // menu popup
#define IDM_Unicode          108  // menu popup
#define IDM_Debug            109  // menu popup
#define IDM_SaveCoordinates  110  // menu popup

typedef struct SETBIN
{
    long   x;
    long   y;
    long   w;
    long   h;
    long   topmost;
    long   savecoordinates;
    long   usescrollbar;
    long   debug;
    long   unicode;
}t_SETBIN;

typedef struct PROP
{
    t_SETBIN bin;
    HBRUSH backbrush;
    HWND   hWnd;
    HWND   hCtrl;
}t_PROP;

t_PROP gP;

BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;

case DLL_PROCESS_DETACH:
break;

case DLL_THREAD_ATTACH:
break;

case DLL_THREAD_DETACH:
break;
}

/* Returns TRUE on success, FALSE on failure */
return TRUE;
}


void zLoadSaveCoordinates (IN long RW)
{
    HANDLE hFile;
    DWORD dwBytes = 0;

    WCHAR zPath[MAX_PATH];
    __stosb((LPBYTE)&zPath, 0, MAX_PATH * 2);
    GetTempPath(MAX_PATH - 12, zPath);
    lstrcat(zPath, L"zTrace3.cfg");

    if (RW)
    {
        hFile = CreateFile(zPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile != INVALID_HANDLE_VALUE)
        {
            WriteFile(hFile, &gP.bin, sizeof(gP.bin), &dwBytes, NULL);
            CloseHandle(hFile);
        }
    }
    else
    {
        __stosb((LPBYTE)&gP.bin, 0, sizeof(gP.bin));
        hFile = CreateFile(zPath, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile != INVALID_HANDLE_VALUE)
        {
            DWORD FileSizeHigh = 0;
            if (GetFileSize(hFile, &FileSizeHigh) == sizeof(gP.bin) && FileSizeHigh == 0)
            {
                ReadFile(hFile, &gP.bin, sizeof(gP.bin), &dwBytes, NULL);
                CloseHandle(hFile);
            }
        }

        if ((gP.bin.w == 0) || (gP.bin.h == 0))
        {
            gP.bin.w = MIN_WIDTH;
            gP.bin.h = MIN_HEIGHT;
            gP.bin.x = 0;
            gP.bin.y = 0;
        }
    }
}

void zDebug (WCHAR* zMessage)
{
    static HANDLE hDebug = NULL;
    if (!zMessage)
    {
        if (hDebug)
        {
            CloseHandle(hDebug);
            hDebug = NULL;
        }
        return;
    }
    long Creation = 0;
    if (*zMessage)
    {
        DWORD BytesWritten = 0;
        if (!hDebug)
        {
            hDebug = CreateFile(L"zDebug.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
            if (hDebug)
                Creation = -1;
        }
        if (hDebug)
        {
            if (gP.bin.unicode)   // UNICODE
            {
                WriteFile(hDebug, zMessage, lstrlen(zMessage), &BytesWritten, NULL);
                WriteFile(hDebug, L"\r\n", 4, &BytesWritten, NULL);
            }
            else                  // ANSI
            {
                if (Creation)
                    WriteFile(hDebug, "\xEF\xBB\xBF", 3, &BytesWritten, NULL);    // UTF-8 BOM
                long length = WideCharToMultiByte(CP_UTF8, 0, zMessage, -1, NULL, 0, NULL, NULL);
                if (length > 1)   // excluding NUL terminator
                {
                    LPSTR buffer = (LPSTR)GlobalAlloc(GPTR, length);
                    if (buffer)
                    {
                        WideCharToMultiByte(CP_UTF8, 0, zMessage, -1, buffer, length, NULL, NULL);
                        WriteFile(hDebug, buffer, length - 1, &BytesWritten, NULL);
                        WriteFile(hDebug, "\r\n", 2, &BytesWritten, NULL);
                        GlobalFree(buffer);
                    }
                }
            }
        }
    }
}

void SendUnicodeToClipboard(HWND hWnd)
{
    long nCount = (long)SendMessage(gP.hCtrl, LB_GETCOUNT, 0L, 0L);
    if (nCount > 0)
    {
        long K, index, cch, bufsize = 0;
        long *pSelItems = NULL;
        long nSelItems = (long)SendMessage(gP.hCtrl, LB_GETSELCOUNT, 0L, 0L);
        if (nSelItems > 0)
        {
            nCount = 0;
            pSelItems = (long *)GlobalAlloc(GPTR, nSelItems * sizeof(long));
            if (pSelItems)
            {
                nCount = nSelItems;
                SendMessage(gP.hCtrl, LB_GETSELITEMS, nSelItems, (LPARAM)pSelItems);
            }
        }
        for (K = 0; K < nCount; K++)
        {
            index = pSelItems ? pSelItems[K] : K;
            cch = (long)SendMessage(gP.hCtrl, LB_GETTEXTLEN, (WPARAM)index, 0L);
            if (cch > 0)
                bufsize += cch + 2;
        }
        if (bufsize > 0)
        {
            HGLOBAL hClipData = GlobalAlloc(GHND | GMEM_DDESHARE, (bufsize + 1) * sizeof(WCHAR));
            LPTSTR  buffer = (LPTSTR)GlobalLock(hClipData);
            int offset = 0;
            for (K = 0; K < nCount; K++)
            {
                index = pSelItems ? pSelItems[K] : K;
                cch = (long)SendMessage(gP.hCtrl, LB_GETTEXTLEN, (WPARAM)index, 0L);
                if (cch > 0)
                {
                    if ((offset + cch + 2) > bufsize)
                        break;
                    cch = (long)SendMessage(gP.hCtrl, LB_GETTEXT, (WPARAM)index, (LPARAM)(buffer + offset));
                    offset += cch;
                    buffer[offset++] = '\r';
                    buffer[offset++] = '\n';
                }
            }
            buffer[bufsize] = 0;
            GlobalUnlock(hClipData);
            if (OpenClipboard(0))
            {
                EmptyClipboard();
                SetClipboardData(CF_UNICODETEXT, hClipData);
                CloseClipboard();
            }
            else
                GlobalFree(hClipData);
        }
    }
}

void DebugRefresh(IN HWND hWnd)
{
    if (gP.bin.debug)
    {
        long nCount = (long)SendMessage(gP.hCtrl, LB_GETCOUNT, 0, 0);
        if (nCount > 0)
        {
            for (long i = 0; i < nCount; i++)
            {
                long cch = (long)SendMessage(gP.hCtrl, LB_GETTEXTLEN, (WPARAM)i, 0L);
                if (cch > 0)
                {
                    LPTSTR pStr = (LPTSTR)GlobalAlloc(GPTR, (cch + 1) * sizeof(WCHAR));
                    if (pStr)
                    {
                        cch = (long)SendMessage(gP.hCtrl, LB_GETTEXT, (WPARAM)i, (LPARAM)pStr);
                        zDebug((LPWSTR)pStr);
                        GlobalFree(pStr);
                    }
                }
            }
        }
    }
    else
        zDebug(NULL); // Close zDebug.txt if already open.
}

LRESULT CALLBACK ToolProc(IN HWND hWnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
{
    RECT rc, rw;
    long nCount;
    HMENU hMenu;

    switch (uMsg)
    {
    case WM_CREATE:
        gP.backbrush = CreateSolidBrush(0x00FFFF);
        break;

    case WM_GETMINMAXINFO:
        SetRect(&rc, 0, 0, MIN_WIDTH, MIN_HEIGHT);
        AdjustWindowRectEx(&rc, WND_Style, FALSE, WND_ExStyle);  // Adjust Window To True Requested Size
        ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = rc.right;
        ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = rc.bottom;
        break;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDCANCEL:
            if (HIWORD(wParam) == BN_CLICKED)
            {
                SendMessage(hWnd, WM_CLOSE, 0, 0);
                return 0;
            }
            break;

        case IDM_About:
        // change here to MessageBoxA because pb with // why?
            MessageBoxA(0,
                        "               Debugging window\n"
                        "\n"
                        "  Copyright © 2017 Patrice TERRIER\n"
                        "          pterrier@zapsolution.com\n"
                        "\n"
                        "        http://www.zapsolution.com \n",
                        A_CAPTION , MB_OK);
            break;

        case IDM_Hscroll:
            gP.bin.usescrollbar = !gP.bin.usescrollbar;
            if (gP.bin.usescrollbar)
            {
                ShowScrollBar(gP.hCtrl, SB_HORZ, TRUE);
                SendMessage(gP.hCtrl, LB_SETHORIZONTALEXTENT, HORIZONTAL_EXTENT, 0);
            }
            else
            {
                SendMessage(gP.hCtrl, LB_SETHORIZONTALEXTENT, 1, 0);
                ShowScrollBar(gP.hCtrl, SB_HORZ, FALSE);
            }
            UpdateWindow(gP.hCtrl);
            break;

        case IDM_Print:
            nCount = (long)SendMessage(gP.hCtrl, LB_GETCOUNT, 0L, 0L);
            if (nCount > 0)
            {
                PRINTDLG pd;
                __stosb((LPBYTE)&pd, 0, sizeof(pd));
                pd.lStructSize = sizeof(pd);
                // get rid of PD_RETURNDEFAULT on the line below if you'd like to
                // see the "Printer Settings" dialog!
                pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
                if (PrintDlg(&pd))
                {
                    HDC hPrinter = pd.hDC;

                    HFONT hOldfont, hFont;
                    hFont = (HFONT)GetStockObject(ANSI_FIXED_FONT);

                    if (hOldfont = (HFONT)SelectObject(pd.hDC, hFont))
                    {
                        TEXTMETRIC tm;
                        __stosb((LPBYTE)&tm, 0, sizeof(tm));
                        GetTextMetrics(pd.hDC, &tm);

                        long yChar = tm.tmHeight + tm.tmExternalLeading;
                        //long nLinesPerPage = GetDeviceCaps(pd.hDC, VERTRES) / yChar;
                        //long nCharsPerLine = GetDeviceCaps(pd.hDC, HORZRES) / tm.tmAveCharWidth;

                        DOCINFO di;
                        __stosb((LPBYTE)&di, 0, sizeof(di));
                        di.cbSize = sizeof(di);
                        StartDoc(hPrinter, &di);
                        StartPage(hPrinter);
                        {
                            long* pSelItems = NULL;
                            long nSelItems = (long)SendMessage(gP.hCtrl, LB_GETSELCOUNT, 0L, 0L);
                            if (nSelItems > 0)
                            {
                                nCount = 0;
                                pSelItems = (long*)GlobalAlloc(GPTR, nSelItems * sizeof(long));
                                if (pSelItems)
                                {
                                    nCount = nSelItems;
                                    SendMessage(gP.hCtrl, LB_GETSELITEMS, nSelItems, (LPARAM)pSelItems);
                                }
                            }
                            for (long i = 0; i < nCount; i++)
                            {
                                long index = pSelItems ? pSelItems[i] : i;
                                long cch = (long)SendMessage(gP.hCtrl, LB_GETTEXTLEN, (WPARAM)index, 0L);
                                if (cch > 0)
                                {
                                    LPTSTR pStr = (LPTSTR)GlobalAlloc(GPTR, (cch + 1) * sizeof(WCHAR));
                                    if (pStr)
                                    {
                                        cch = (long)SendMessage(gP.hCtrl, LB_GETTEXT, (WPARAM)index, (LPARAM)pStr);
                                        TextOut(pd.hDC, 0, (yChar * i), pStr, cch);
                                        GlobalFree(pStr);
                                    }
                                }
                            }
                            if (pSelItems)
GlobalFree(pSelItems);
                        }
                        EndPage(hPrinter);
                        EndDoc(hPrinter);
                        SelectObject(pd.hDC, hOldfont); // Good pratice
                        DeleteDC(hPrinter);
                    }
                }
            }
            break;

        case IDM_CopyToClipboard:
            SendUnicodeToClipboard(hWnd);
            break;

        case IDM_ClearContent:
            SendMessage(gP.hCtrl, LB_RESETCONTENT, 0, 0);
            break;

        case IDM_TopMost:
            gP.bin.topmost = !gP.bin.topmost;
            //if (gP.bin.topmost) {
            //    SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
            //} else {
            //    SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
            //}
            SetWindowPos(hWnd, gP.bin.topmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
            break;

        case IDM_Unicode:
            gP.bin.unicode = !gP.bin.unicode;
            DebugRefresh(hWnd);
            break;

        case IDM_Debug:
            gP.bin.debug = !gP.bin.debug;
            DebugRefresh(hWnd);
            break;

        case IDM_SaveCoordinates:
            gP.bin.savecoordinates = !gP.bin.savecoordinates;
            break;
        }
        break;

    case WM_CTLCOLORDLG:
        SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
        return (LRESULT)GetStockObject(NULL_BRUSH);

    case WM_CTLCOLORLISTBOX:
        // wParam is handle of control's display context (hDC)
        // lParam is handle of control
        //------------------------------------------------------
        if ((HWND)lParam == gP.hCtrl)
        {
            SetBkColor((HDC) wParam, 0x00FFFF);
            return (LRESULT) gP.backbrush;
        }
        break;

    case WM_RBUTTONDOWN:
        hMenu = CreatePopupMenu();
        if (hMenu)
        {
            long menuStyle;
            AppendMenu(hMenu, MF_STRING, IDM_About            , L"About");
            AppendMenu(hMenu, MF_SEPARATOR, 102               , L"");
            if (gP.bin.usescrollbar)
                menuStyle = MF_STRING | MF_CHECKED;
            else
                menuStyle = MF_STRING;
            AppendMenu(hMenu, menuStyle,  IDM_Hscroll         , L"Use horizontal scrollbar");
            AppendMenu(hMenu, MF_STRING,  IDM_Print           , L"Send selection to printer");
            AppendMenu(hMenu, MF_STRING,  IDM_CopyToClipboard , L"Copy selection to clipboard");
            AppendMenu(hMenu, MF_STRING,  IDM_ClearContent    , L"Clear content");
            if (gP.bin.topmost)
                menuStyle = MF_STRING | MF_CHECKED;
            else
                menuStyle = MF_STRING;
            AppendMenu(hMenu, menuStyle,  IDM_TopMost         , L"Set window TopMost");
            if (gP.bin.unicode)
                menuStyle = MF_STRING | MF_CHECKED;
            else
                menuStyle = MF_STRING;
            AppendMenu(hMenu, MF_SEPARATOR, 102               , L"");
            AppendMenu(hMenu, menuStyle,  IDM_Unicode         , L"Use Unicode in zDebug.txt");
            if (gP.bin.debug)
                menuStyle = MF_STRING | MF_CHECKED;
            else
                menuStyle = MF_STRING;
            AppendMenu(hMenu, menuStyle,  IDM_Debug           , L"Create zDebug.txt report");
            if (gP.bin.savecoordinates)
                menuStyle = MF_STRING | MF_CHECKED;
            else
                menuStyle = MF_STRING;
            AppendMenu(hMenu, MF_SEPARATOR, 102               , L"");
            AppendMenu(hMenu, menuStyle,  IDM_SaveCoordinates , L"Save window coordinates");

            POINT p;
            GetCursorPos(&p);
            long nChoice = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, p.x, p.y, hWnd, NULL);
            DestroyMenu(hMenu);
            if (nChoice)
                SendMessage(hWnd, WM_COMMAND, MAKELONG(nChoice, 0), 0);
        }
        break;

    case WM_SIZE:
        if (wParam == SIZE_MINIMIZED)
            break;
        gP.bin.w = LOWORD(lParam);
        gP.bin.h = HIWORD(lParam);
        MoveWindow(gP.hCtrl, 0, 0, gP.bin.w, gP.bin.h, TRUE);
        UpdateWindow(hWnd);
    case WM_MOVE:
        GetWindowRect(hWnd, &rw);
        gP.bin.x = rw.left;
        gP.bin.y = rw.top;
        break;

    case WM_DESTROY:
        if (gP.backbrush)
        {
            DeleteObject(gP.backbrush);
            gP.backbrush = 0;
            zLoadSaveCoordinates(1);
        }
        zDebug(NULL);
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

long AddString(IN HWND hCtrl, WCHAR* zPtr)
{
    long nRet = LB_ERR;
    if (zPtr)
    {
        if (gP.bin.debug)
            zDebug(zPtr);
        nRet = (long) SendMessage(hCtrl, LB_ADDSTRING, 0, (LPARAM) zPtr);
        SendMessage(hCtrl, LB_SETTOPINDEX, (WPARAM) nRet, 0);
    }
    return nRet;
}

DWORD WINAPI ShowPopup(IN WCHAR* zPtr)
{
    DWORD nRet = 0;
    HINSTANCE hInstance = GetModuleHandle(NULL);

    WNDCLASSEX wcx;
    __stosb((LPBYTE)&wcx, 0, sizeof(wcx));
    wcx.cbSize = sizeof(wcx);
    long IsInitialized = GetClassInfoEx(hInstance, WND_CAPTION, &wcx);
    if (IsInitialized    == 0)
    {
        wcx.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
        wcx.lpfnWndProc   = &ToolProc;
        wcx.cbClsExtra    = 0;
        wcx.cbWndExtra    = 0;
        wcx.hInstance     = hInstance;
        wcx.hIcon         = 0;
        wcx.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wcx.hbrBackground = (HBRUSH) COLOR_BTNSHADOW;
        wcx.lpszMenuName  = NULL;
        wcx.lpszClassName = WND_CAPTION;
        wcx.hIconSm       = wcx.hIcon;
        if (RegisterClassEx(&wcx))
            IsInitialized = TRUE;
    }
    if (IsInitialized)
    {
        zLoadSaveCoordinates(0);
        RECT rc;
        SetRect(&rc, 0, 0, gP.bin.w, gP.bin.h);
        AdjustWindowRectEx(&rc, WND_Style, FALSE, WND_ExStyle);  // Adjust Window To True Requested Size
        gP.hWnd = CreateWindowEx(WND_ExStyle, WND_CAPTION, WND_CAPTION, WND_Style, gP.bin.x, gP.bin.y, rc.right - rc.left, rc.bottom - rc.top, 0, 0, hInstance, NULL);
        if (gP.hWnd)
        {
            DWORD nStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | LBS_MULTIPLESEL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | LBS_DISABLENOSCROLL;
            gP.hCtrl = CreateWindowEx(0, L"ListBox", NULL, nStyle, 0, 0, gP.bin.w, gP.bin.h, gP.hWnd, (HMENU) ID_LISTBOX, hInstance, NULL);

            HFONT hFont = CreateFont(-13, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, FF_MODERN | FIXED_PITCH, L"Courier New");
            if (hFont) SendMessage(gP.hCtrl, WM_SETFONT, (WPARAM)hFont, 0L);

            AddString(gP.hCtrl, zPtr);

            if (gP.bin.usescrollbar)
            {
                SendMessage(gP.hCtrl, LB_SETHORIZONTALEXTENT, HORIZONTAL_EXTENT, 0);
                ShowScrollBar(gP.hCtrl, SB_HORZ, TRUE);
            }
            else
                ShowScrollBar(gP.hCtrl, SB_HORZ, FALSE);


            if (gP.bin.topmost)
                SetWindowPos(gP.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
            else
                ShowWindow(gP.hWnd, SW_SHOW);

            UpdateWindow(gP.hWnd);

            MSG msg;
            while (GetMessage(&msg, NULL, 0, 0))
            {
                // Easier to detect the right mouse button click on the listBox from the message pump
                if ((msg.hwnd == gP.hCtrl) && (msg.message == WM_RBUTTONDOWN))
                    ToolProc(gP.hWnd, WM_RBUTTONDOWN, 0, 0);
                else
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }

            DeleteObject(hFont);
            nRet = (DWORD)msg.wParam;
        }
    }
    return nRet;
}

#ifdef __cplusplus
  extern "C" {
#endif
    __declspec(dllexport)long   zTrace(WCHAR* zPtr)
    {
        long nRet = LB_ERR;
        if (gP.hWnd == NULL)
        {
            DWORD dwThreadId = 0;
            HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ShowPopup, zPtr, 0, &dwThreadId);
            if (hThread)
            {
                Sleep(100);
                CloseHandle(hThread);
                nRet = 0;
            }
        }
        else
            nRet = AddString(gP.hCtrl, zPtr);
        return nRet;
    }
#ifdef __cplusplus
  }
#endif




it worked perfectly

the bat file to compile and create the interface for dll  libzTrace32.dll.a  (for mingw  toolchain compilers )

@echo off

Rem check here  where is your main compiler folder
SET var=E:\mingw-w64-5.3.0\mingw32\

Rem check here also where are your libgdi32.a  & libcomdlg32.a
SET var2=%var%i686-w64-mingw32\

SET lib32=%var2%lib\



@REM TODO: Set PATH's for this session.
SET PATH=%var%bin;%var%i686-w64-mingw32\bin;

SET MINGW_INCLUDE=%var%include
SET MINGW_LIB=%var%lib
echo.
echo  Path for compilation  : %var%
echo.
echo.

@echo Compile
gcc  -c zTrace32.c -o zTrace32.o
@echo.
@echo link
gcc -shared -o zTrace32.dll zTrace32.o %lib32%libgdi32.a %lib32%libcomdlg32.a  -s -Wl,--out-implib,libzTrace32.dll.a
@echo.
pause


it produce 25ko dll

i suppose it works also on 64bit compiler

Encore merci pour ce super outil très pratique, et pour avoir publié le code également.

Je le diffuse largement autour de moi...  en indiquant l'auteur naturellement.

bye


attached the codes and 32 dll




Title: Re: zTrace 1.52 (debugging utility)
Post by: Patrice Terrier on August 11, 2017, 08:10:36 PM
Le code est également disponible sur codeproject
https://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=1378591