• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

zTrace 1.52 (debugging utility)

Started by Patrice Terrier, April 05, 2009, 12:43:44 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

Again, i have absolutly no knowledge of VB.

Did you try it without the VB6 IDE, i mean as a real standalone EXE ?
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

John Aadnoey

#46
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.

Patrice Terrier

Then this means that when you run it within the VB6 IDE, it runs as p-code not native code, that's it.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

John Aadnoey

#48
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.

Norbert Spoerl

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.

Patrice Terrier

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!
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

John Aadnoey

Ah oki. That explains it. Then I'll just keep on using it on my pure PB hobby projects.

Thanks all

Norm Cook

#52
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

Patrice Terrier

#53
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))
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

George Bleck

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.


       
  • If %zTrace is defined as a positive number, zTrace and zDebug work exactly as expected.
  • If %zTrace is defined as a negative number, zTrace and zDebug both act like zDebug and send to zDebug.txt (allows you to easily switch to "silent" debugging).
  • If %zTrace is 0, not defined,  or REM'd out, then all zTrace/zDebug lines are compiled as #UTILITY commands, in other words, they are ignored by the compiler.
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.

Patrice Terrier

#55
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

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

James C. Fuller

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

Patrice Terrier

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 ;)

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

Emil

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

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Marc Pons

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