• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

zTrace 2.02 (C/C++ version 32/64-bit)

Started by Patrice Terrier, May 06, 2013, 05:50:36 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

Here is the full translation of my zTrace utility to C/C++, it works in 32 and 64-bit

Note: This version is, UNICODE only, see the new SendUnicodeToClipboard procedure that is using the CF_UNICODETEXT parameter.

The 32-bit DLL is within the \Release subfolder.
The 64-bit DLL is within the \x64\Release subfolder.

The project must be compiled with the /Gz option (stdcall) for WINAPI compatibility.

And here is the full source code of the project:

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

#include <windows.h>
#include <iostream>
using namespace std;
#include <time.h>

#define ExportC extern "C" _declspec (dllexport)

#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff))
#define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))
#define UBOUND(T) (T.size())
#define MAKLNG(a, b) ((LONG) (((WORD) (a)) | ((DWORD) ((WORD) (b))) << 16))

static wchar_t  *$NULL        = L"";
static wchar_t  *$ZTRACE      = L"zTrace 2.02 ";

const wchar_t   *$ANTI        = L"\\";

//----------------------------------------------------------------------

const DWORD dwStyle = WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
const DWORD dwExStyle = WS_EX_TOOLWINDOW;

const int HORIZONTAL_EXTENT   = 6000; // Maximum value for the horizontal scrollbar
const int MIN_WIDTH           = 300;  // default client width size
const int MIN_HEIGHT          = 65;   // default client height size

const int ID_LISTBOX          = 1;

const int IDM_About           = 101;  // menu popup
const int IDM_Hscroll         = 103;  // menu popup
const int IDM_Print           = 104;  // menu popup
const int IDM_CopyToClipboard = 105;  // menu popup
const int IDM_ClearContent    = 106;  // menu popup
const int IDM_TopMost         = 107;  // menu popup
const int IDM_Debug           = 108;  // menu popup
const int IDM_SaveCoordinates = 109;  // menu popup

struct PROP {
    HBRUSH backbrush;
    long   x;
    long   y;
    long   w;
    long   h;
    long   savecoordinates;
    long   topmost;
    long   debug;
    long   usescrollbar;
    WCHAR  caption[24];
};

PROP gP;

wstring DateTime() {
    time_t now = time(0);
    tm tstruct = { 0 };
    WCHAR buf[80] = { 0 };
    if (localtime_s(&tstruct, &now) == 0) {;
        wcsftime(buf, sizeof(buf), L"%Y%m%d,%X", &tstruct);
    }
    return buf;
}

wstring STRL$(IN long N) {
    WCHAR longstr[33] = {0};
    _ltow_s(N, longstr, 10);
    return (WCHAR*) longstr;
}

wstring LEFT$(IN wstring sBuf, IN long nLeft) {
    wstring sResult = $NULL;
    LONG_PTR nLength = max(min((long)sBuf.length(), nLeft), 0);
    if (nLength) {
        sResult = sBuf.substr(0, nLength);
    }
    return sResult;
}

wstring RTRIM$(IN wstring sBuf, IN wstring sChar) {
    wstring sResult = sBuf;
    LONG_PTR nLength = sBuf.length();
    if (nLength && (sChar.length())) {
        //sChar = sChar.substr(0, 1);
        while (nLength > 0) {
            // if (*sBuf.substr(nLength - 1, 1).c_str() == *sChar.c_str()) {
            // This is the sChar ANY search version
            if (std::wstring::npos != sChar.find(sBuf.substr(nLength - 1, 1))) {
                --nLength;
            } else {
                break;
            }
        }
        sResult = sBuf.substr(0, nLength);
    }
    return sResult;
}

string rtrim$(IN string sBuf, IN string sChar) {
    string sResult = sBuf;
    LONG_PTR nLength = sBuf.length();
    if (nLength && (sChar.length())) {
        //sChar = sChar.substr(0, 1);
        while (nLength > 0) {
            // if (*sBuf.substr(nLength - 1, 1).c_str() == *sChar.c_str()) {
            // This is the sChar ANY search version
            if (std::string::npos != sChar.find(sBuf.substr(nLength - 1, 1))) {
                --nLength;
            } else {
                break;
            }
        }
        sResult = sBuf.substr(0, nLength);
    }
    return sResult;
}

DWORD FileSize(IN WCHAR* szFileSpec) {
    WIN32_FIND_DATA fd = {0};
    DWORD nRet = 0;
    if (wcslen(szFileSpec)) {
        HANDLE hFind;
        hFind = FindFirstFile(szFileSpec, &fd);
        if (hFind != INVALID_HANDLE_VALUE) {
            FindClose(hFind);
            nRet = fd.nFileSizeLow;
        }
    }
    return nRet;
}

WCHAR* TEMPpath () {
    static WCHAR buf[MAX_PATH];
    DWORD nSize = GetTempPath(GetTempPath(NULL, NULL), &buf[0]);
    if (nSize) {
        if (FileSize(buf) == 0) { CreateDirectory(buf, NULL); }
    }
    return buf;
}

wstring zGetTextListbox(IN HWND hListBox, IN long nItem) {
    wstring sResult;
    long nLength = (long) SendMessage(hListBox, LB_GETTEXTLEN, nItem, 0);
    WCHAR* sItem = new WCHAR[(nLength + 1) * sizeof(WCHAR)];
    memset(&sItem[0], 0, (nLength + 1) * sizeof(WCHAR));
    nLength = (long) SendMessage(hListBox, LB_GETTEXT, (WPARAM) nItem, (LPARAM) &sItem[0]);
    sResult = (WCHAR*) sItem;
    delete [] sItem;
    return sResult;
}

string parse$(IN string sMain, IN long nIndex) {
    string sResult;
    string sDelim = ",";
    long nLength = (long) sDelim.length();
    sMain = rtrim$(sMain, sDelim); sMain += sDelim;
    if (sMain.length() && nLength) {
        size_t prev_pos = 0, pos = 0, nCount = 0;
        while( (pos = sMain.find(sDelim, pos)) != std::string::npos ) {
            string substring(sMain.substr(prev_pos, pos - prev_pos));
            ++nCount;
            if (nCount == nIndex) { sResult = substring; break; }
            prev_pos = ++pos;
        }
    }
    return sResult;
}

string str$(IN long N) {
    char longstr[33] = {0};
    _itoa_s(N, longstr, 10);
    return (char*) longstr;
}

long LongValA(IN string sNum) {
    return atol(sNum.c_str());
}

void zLoadSaveCoordinates (OUT long &x, OUT long &y, OUT long &w, OUT long &h, IN long RW) {
    HANDLE hFile;
    static string WasCoordinates;
    DWORD dwBytes = 0;
    wstring sFileName = TEMPpath();
    if (sizeof(LONG_PTR) > 4 ) {
        sFileName += L"zTrace64.cfg";
    } else {
        sFileName += L"zTrace32.cfg";
    }
    if (RW) {
        string sLim = ",";
        WasCoordinates =  str$(x);                  WasCoordinates += sLim;
        WasCoordinates += str$(y);                  WasCoordinates += sLim;
        WasCoordinates += str$(w);                  WasCoordinates += sLim;
        WasCoordinates += str$(h);                  WasCoordinates += sLim;
        WasCoordinates += str$(gP.topmost);         WasCoordinates += sLim;
        WasCoordinates += str$(gP.savecoordinates); WasCoordinates += sLim;
        WasCoordinates += str$(gP.usescrollbar);    WasCoordinates += sLim;
        WasCoordinates += str$(gP.debug);
        hFile = CreateFile((WCHAR*) sFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile != INVALID_HANDLE_VALUE) {
            WriteFile(hFile, (char*) WasCoordinates.c_str(), (DWORD) WasCoordinates.length(), &dwBytes, NULL);
            CloseHandle(hFile);
        }

    } else {
        if (WasCoordinates.length() == 0) {
            DWORD BufferSize = FileSize((WCHAR*) sFileName.c_str());
            if (BufferSize) {
                hFile = CreateFile((WCHAR*) sFileName.c_str(), GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
                if (hFile != INVALID_HANDLE_VALUE) {
                    WasCoordinates.assign(BufferSize, 32);
                    ReadFile(hFile, (char*) WasCoordinates.c_str(), BufferSize, &dwBytes, NULL);
                    CloseHandle(hFile);
                }
            }
            x = LongValA(parse$(WasCoordinates, 1));
            y = LongValA(parse$(WasCoordinates, 2));
            w = LongValA(parse$(WasCoordinates, 3));
            h = LongValA(parse$(WasCoordinates, 4));
            gP.topmost          = LongValA(parse$(WasCoordinates, 5));
            gP.savecoordinates  = LongValA(parse$(WasCoordinates, 6)); if (gP.savecoordinates == 0) { w = 0; }
            gP.usescrollbar     = LongValA(parse$(WasCoordinates, 7));
            gP.debug            = LongValA(parse$(WasCoordinates, 8));
        }
        if ((w == 0) || (h == 0)) { w = MIN_WIDTH; h = MIN_HEIGHT; x = 0; y = 0; }
    }
}

long WstringToChar(IN wstring sTxt, OUT char* szTxt) {
    size_t convertedChars = 0;
    wcstombs_s(&convertedChars, szTxt, sTxt.length() + 1, sTxt.c_str(), _TRUNCATE);
    return (long) max(convertedChars - 1, 0);
}

// Copy any debug string to a sequential ASCII file.
void zDebug (WCHAR* zMessage) {
    static HANDLE hDebug;
    static long NeverBeenThere;
    wstring sMessage;
    long nLen = (long) wcslen(zMessage);
    if (hDebug && (nLen == 0)) {
        CloseHandle(hDebug);
        NeverBeenThere = 0;
        return;
    }
    if (nLen) {
        if (NeverBeenThere == 0) {
            NeverBeenThere = -1;
            wstring sFileName = L"zDebug.txt";
            hDebug = CreateFile((WCHAR*) sFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        }
        if (hDebug) {
            sMessage = (WCHAR*) zMessage; sMessage += L"\r\n";
            DWORD BytesWritten = 0;
            DWORD BufferSize = (DWORD) sMessage.length() + 1;
            char* buffer = new char[BufferSize];
            WstringToChar(sMessage, buffer);
            WriteFile(hDebug, buffer, BufferSize, &BytesWritten, NULL);
            delete [] buffer;
        }
    }
}

void SendUnicodeToClipboard (IN HWND hWnd) {
    HWND hCtrl = GetDlgItem(hWnd, ID_LISTBOX);
    long nCount = (long) SendMessage(hCtrl, LB_GETCOUNT, 0, 0);
    if (nCount > 0) {
        long nSelItems = (long) SendMessage(hCtrl, LB_GETSELCOUNT, 0, 0);
        wstring sBuffer = $NULL;
        long K;
        if (nSelItems > 0) {
            long* SelItem = new long[nSelItems];
            nCount = (long) SendMessage(hCtrl, LB_GETSELITEMS, nSelItems, (LPARAM) &SelItem[0]);
            for (K = 0; K < nSelItems; ++K) {
                nCount = SelItem[K];
                sBuffer +=  zGetTextListbox(hCtrl, SelItem[K]); sBuffer += L"\r\n";
            }
            delete [] SelItem;
        } else {
            for (K = 0; K < nCount; ++K) {
                sBuffer += zGetTextListbox(hCtrl, K); sBuffer += L"\n";
            }
        }
        nCount = (long) sBuffer.length() + 1;
        WCHAR* buffer = new WCHAR[nCount];
        memset(&buffer[0], 0, nCount * sizeof(WCHAR)); // I like to clear the new memory buffer with NULLs
        MoveMemory(&buffer[0], (WCHAR*) sBuffer.c_str(), nCount * sizeof(WCHAR));
        HGLOBAL hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, nCount * sizeof(WCHAR));
        LPVOID hGlob = GlobalLock(hClipData);
        MoveMemory(hGlob, &buffer[0], nCount * sizeof(WCHAR));
        GlobalUnlock(hClipData);
        if (OpenClipboard(0)) {
            EmptyClipboard();
            SetClipboardData(CF_UNICODETEXT, hClipData);
            CloseClipboard();
        } else {
            GlobalFree(hClipData);
        }
        delete [] buffer;
    }
}

LRESULT CALLBACK ToolProc (IN HWND hWnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam) {

    RECT rc, rw;
    long K = 0, nCount = 0, nSelItems = 0;
    HWND hCtrl = 0;
    wstring sMessage;
    MINMAXINFO pMM = {0};
    PRINTDLG pd = {0};
    DOCINFO di = {0};
    TEXTMETRIC tm = {0};
    long yChar, nLinesPerPage, nCharsPerLine;

    long wP = LOWORD(wParam);

    switch (uMsg) {

    case WM_CREATE:
         if (gP.backbrush == 0) { gP.backbrush = CreateSolidBrush(0x00FFFF); }
         break;

    case WM_GETMINMAXINFO:
         MoveMemory(&pMM, (MINMAXINFO*) lParam, sizeof(pMM));
         SetRect(&rc, 0, 0, MIN_WIDTH, MIN_HEIGHT);
         AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);  // Adjust Window To True Requested Size
         pMM.ptMinTrackSize.x = rc.right;
         pMM.ptMinTrackSize.y = rc.bottom;
         break;

    case WM_COMMAND:

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

         case IDM_About:
              sMessage =  L"           Debugging window\n\nCopyright © ";
              sMessage += LEFT$(DateTime(), 4);
              sMessage += L" Patrice TERRIER  "
                          L"\n       pterrier@zapsolution.com"
                          L"\n\n          www.zapsolution.com";
              MessageBox(0, (WCHAR*) sMessage.c_str(), gP.caption, MB_OK);
              break;

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

         case IDM_Print:
              hCtrl = GetDlgItem(hWnd, ID_LISTBOX);
              nCount = (long) SendMessage(hCtrl, LB_GETCOUNT, 0, 0);
              if (nCount > 0) {
                  PRINTDLG pd = {0};
                  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;
                      GetTextMetrics(pd.hDC, &tm);

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

                      di.cbSize = sizeof(di);
                      StartDoc(hPrinter, &di);
                          StartPage(hPrinter);
                              nSelItems = (long) SendMessage(hCtrl, LB_GETSELCOUNT, 0, 0);
                              if (nSelItems > 0) {
                                  long* SelItem = new long[nSelItems];
                                  nCount = (long) SendMessage(hCtrl, LB_GETSELITEMS, nSelItems, (LPARAM) &SelItem[0]);
                                  for (K = 0; K < nSelItems; K++) {
                                       sMessage = zGetTextListbox(hCtrl, SelItem[K]);
                                       TextOut(pd.hDC, 0, (yChar * K), (WCHAR*) sMessage.c_str(), (long) sMessage.length());
                                  }
                              } else {
                                  for (K = 0; K < nCount; K++) {
                                       sMessage = zGetTextListbox(hCtrl, K);
                                       TextOut(pd.hDC, 0, (yChar * K), (WCHAR*) sMessage.c_str(), (long) sMessage.length());
                                  }
                              }
                          EndPage(hPrinter);
                      EndDoc(hPrinter);
                      DeleteDC(hPrinter);
                  }
              }
              break;

         case IDM_CopyToClipboard:
              SendUnicodeToClipboard(hWnd);
              break;

         case IDM_ClearContent:
              SendMessage(GetDlgItem(hWnd, ID_LISTBOX), LB_RESETCONTENT, 0, 0);
              break;

         case IDM_TopMost:
              gP.topmost = !gP.topmost;
              if (gP.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);
              }
              break;

         case IDM_Debug:
              gP.debug = !gP.debug ;
              if (gP.debug) {
                  hCtrl = GetDlgItem(hWnd, ID_LISTBOX);
                  nCount = (long) SendMessage(hCtrl, LB_GETCOUNT, 0, 0)   ;
                  if (nCount > 0) {
                      for (K = 0; K < nCount; ++K) {
                          zDebug((WCHAR*) zGetTextListbox(hCtrl, K).c_str());
                      }
                  }
              } else {
                  zDebug($NULL); // Close zDebug.txt if already open.
              }
              break;

         case IDM_SaveCoordinates:
              gP.savecoordinates = !gP.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 (lParam == (LPARAM) GetDlgItem(hWnd, ID_LISTBOX)) {
             SetBkColor((HDC) wParam, 0x00FFFF);
             return (LRESULT) gP.backbrush;
         }
         break;

    case WM_RBUTTONDOWN:
         HMENU hMenu; POINT p;
         long menuStyle, nChoice;
         hMenu = CreatePopupMenu();
         if (hMenu) {
             AppendMenu(hMenu, MF_STRING, IDM_About            , L"About");
             AppendMenu(hMenu, MF_SEPARATOR, 102               , L"");
             if (gP.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.topmost) { menuStyle = MF_STRING | MF_CHECKED; } else { menuStyle = MF_STRING; }
             AppendMenu(hMenu, menuStyle,  IDM_TopMost         , L"Set window TopMost");
             if (gP.debug) { menuStyle = MF_STRING | MF_CHECKED; } else { menuStyle = MF_STRING; }
             AppendMenu(hMenu, menuStyle,  IDM_Debug           , L"Create zDebug.txt report");
             if (gP.savecoordinates) { menuStyle = MF_STRING | MF_CHECKED; } else { menuStyle = MF_STRING; }
             AppendMenu(hMenu, menuStyle,  IDM_SaveCoordinates , L"Save window coordinates");

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

    case WM_MOVE:
         GetWindowRect(hWnd, &rw); gP.x = rw.left; gP.y = rw.top;
         break;

    case WM_SIZE:
         if (wParam != SIZE_MINIMIZED) {
             gP.w = LOWORD(lParam); gP.h = HIWORD(lParam);
             MoveWindow(GetDlgItem(hWnd, ID_LISTBOX), 0, 0, gP.w, gP.h, TRUE);
             UpdateWindow(hWnd);

             GetWindowRect(hWnd, &rw); gP.x = rw.left; gP.y = rw.top;

         }
         break;

    case WM_DESTROY:
         if (gP.backbrush) {
             DeleteObject(gP.backbrush); gP.backbrush = 0;
             zLoadSaveCoordinates (gP.x, gP.y, gP.w, gP.h, 1);
         }
         zDebug($NULL);
         PostQuitMessage(0);
         return 0;

    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

long AddString(IN HWND hCtrl, WCHAR* zPtr) {
    long nRet;
    if (gP.debug) {
        if (zPtr) { 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;
    MSG msg;
    long IsInitialized = 0;
    HWND hWnd, hCtrl;
    HINSTANCE hInstance = GetModuleHandle(NULL);

    WNDCLASSEX wcx = { 0 };
    RECT rc = { 0 };

    wstring sCaption = $ZTRACE; sCaption += STRL$(sizeof(LONG_PTR) * 8); sCaption += L"-bit";
    MoveMemory(&gP.caption[0], (WCHAR*) sCaption.c_str(), sCaption.length() * 2);

    wcx.cbSize = sizeof(wcx);
    IsInitialized = GetClassInfoEx(hInstance, gP.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 = gP.caption;
        wcx.hIconSm       = wcx.hIcon;
        if (RegisterClassEx(&wcx)) { IsInitialized = TRUE; }
    }

    if (IsInitialized) {
        long UseX = 0, UseY = 0, UseW = 0, UseH = 0;
        zLoadSaveCoordinates (UseX, UseY, UseW, UseH, 0);

        SetRect(&rc, 0, 0, UseW, UseH);
        AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);  // Adjust Window To True Requested Size

        hWnd = CreateWindowEx(dwExStyle, gP.caption, gP.caption,
                              dwStyle,
                              UseX, UseY,
                              rc.right - rc.left,  // Calculate Window Width
                              rc.bottom - rc.top,  // Calculate Window Height
                              0, 0, hInstance, NULL);
        if (hWnd) {
            DWORD nStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | LBS_MULTIPLESEL | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | LBS_DISABLENOSCROLL;
            hCtrl = CreateWindowEx(0, L"ListBox", NULL, nStyle, 0, 0, UseW, UseH, hWnd, (HMENU) ID_LISTBOX, hInstance, NULL);
            SendMessage(hCtrl, WM_SETFONT, (WPARAM) GetStockObject(ANSI_FIXED_FONT), 0);
            AddString(hCtrl, zPtr);
            if (gP.usescrollbar) {
                SendMessage(hCtrl, LB_SETHORIZONTALEXTENT, HORIZONTAL_EXTENT, 0);
                ShowScrollBar(hCtrl, SB_HORZ, TRUE);
            } else {
                ShowScrollBar(hCtrl, SB_HORZ, FALSE);
            }
       
            if (gP.topmost) {
                SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
            } else {
                ShowWindow(hWnd, SW_SHOW);
            }
            UpdateWindow(hWnd);
       
            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) && (msg.message == WM_RBUTTONDOWN)) {
                    ToolProc(hWnd, WM_RBUTTONDOWN, 0, 0);
                } else {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
            nRet = (DWORD) msg.wParam;
        }
    }
    return nRet;
}

ExportC long zTrace (IN WCHAR* zPtr) {
    long nRet = 0;
    HWND hWnd = FindWindow(gP.caption, gP.caption);
    if (hWnd == 0) {
        nRet = LB_ERR;
        DWORD dwThreadId = 0;
        HANDLE hThread = CreateThread(NULL,                                  // default security attributes
                                      0,                                     // use default stack size
                                      (LPTHREAD_START_ROUTINE ) ShowPopup,   // thread function name
                                      zPtr,                                  // argument to thread function
                                      0,                                     // use default creation flags
                                      &dwThreadId);                          // returns the thread identifier
        if (hThread) {
            nRet = 0; Sleep(100);
        }
        CloseHandle(hThread);

    } else {
        if (wcslen(zPtr)) { nRet = AddString(GetDlgItem(hWnd, ID_LISTBOX), zPtr); }
    }
    return nRet;
}

BOOL WINAPI DllMain(IN HINSTANCE hDllHandle, IN DWORD nReason, IN LPVOID Reserved) {
    BOOL bRet = TRUE;
    if (nReason == DLL_PROCESS_DETACH) {
        if (gP.backbrush) {
            DeleteObject(gP.backbrush); gP.backbrush = 0;
            zLoadSaveCoordinates (gP.x, gP.y, gP.w, gP.h, 1);
        }
        zDebug($NULL);
    }
    return bRet;
}


The attached ZIP file comprise the C++ source code for the 32-bit and/or the 64-bit version, each one using a different name (zTrace32.dll and zTrace64.dll).

I couldn't work any more without it...   8)
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#1
James--

Be happy, i have added printing support to zTrace:
Quotecase IDM_Print:
              hCtrl = GetDlgItem(hWnd, ID_LISTBOX);
              nCount = (long) SendMessage(hCtrl, LB_GETCOUNT, 0, 0);
              if (nCount > 0) {
                  PRINTDLG pd = {0};
                  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;
                      GetTextMetrics(pd.hDC, &tm);

                      yChar = tm.tmHeight + tm.tmExternalLeading;
                      nLinesPerPage = GetDeviceCaps(pd.hDC, VERTRES) / yChar;
                      nCharsPerLine = GetDeviceCaps(pd.hDC, HORZRES) / tm.tmAveCharWidth;
                 
                      di.cbSize = sizeof(di);
                      StartDoc(hPrinter, &di);
                          StartPage(hPrinter);
                              nSelItems = (long) SendMessage(hCtrl, LB_GETSELCOUNT, 0, 0);
                              if (nSelItems > 0) {
                                  long* SelItem = new long[nSelItems];
                                  nCount = (long) SendMessage(hCtrl, LB_GETSELITEMS, nSelItems, (LPARAM) &SelItem[0]);
                                  for (K = 0; K < nSelItems; K++) {
                                       sMessage = zGetTextListbox(hCtrl, SelItem[K]);
                                       TextOut(pd.hDC, 0, (yChar * K), (WCHAR*) sMessage.c_str(), (long) sMessage.length());
                                  } }
                              else {
                                  for (K = 0; K < nCount; K++) {
                                       sMessage = zGetTextListbox(hCtrl, K);
                                       TextOut(pd.hDC, 0, (yChar * K), (WCHAR*) sMessage.c_str(), (long) sMessage.length());
                                  }
                              }
                          EndPage(hPrinter);
                      EndDoc(hPrinter);
                      DeleteDC(hPrinter);
                  }
              }
              break;



And here is the helper function to use zTrace from inside your code:

#define long_proc typedef long (__stdcall *zProc)
Quotelong zTrace (IN wstring 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*);
        zProc hProc = (zProc) GetProcAddress(hDll, "zTrace");
        if (hProc) { nRet = hProc((WCHAR*) sPtr.c_str()); }
    }
    return nRet;
}

The full VS2010 project is attached to the first post of this thread.
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

I did put a copy of the zTrace C++ project on CodeProject.

Now let us see how they will rate this piece of SDK code  :)
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

James C. Fuller

Patrice,
  Has there been an update. I notice it is a year old and you are always tinkering :)

James

Patrice Terrier

#4
The latest PowerBASIC version has been posted there.

Switching to plain SDK flat API results in a {massive} size reduction from 49664 bytes down to 27648 bytes.  ;)

The most significant saving was to replace the XPRINT encapsulation with direct API call.

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

Patrice Terrier

The first post of this thread has been updated to zTrace version 2.02.
both C++ 32-bit and 64-bit are inside of the zip file, under the name zTrace32.dll and zTrace64.dll.

There was a wrong "{" "}" combination in version 2.01 that was not detected by the compiler, and the C++ code has been rewritten to match as close as possible the one used in the PowerBASIC version.

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

James C. Fuller

Patrice,
  Thank you for the update of the most used tool in my toolbox.

James

Patrice Terrier

#7
QuoteThank you for the update of the most used tool in my toolbox.
cool 8)

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

James C. Fuller

Patrice,
  The debug.txt file is not an ascii text file on Windows 10.

James

James C. Fuller

Patrice,
  I fixed it for 64bit. I don't do 32bit anymore .
The debug.txt file had a zero as the first character of every line after the first line.

In void zDebug(WCHAR* zMessage)
I changed
DWORD BufferSize = (DWORD) sMessage.length() + 1;
To
DWORD BufferSize = (DWORD)sMessage.length();

James


Patrice Terrier

James

Thanks for the feedback, i have fixed it.

The other solution would be to use only WCHAR rather than a mix of WCHAR/WSTRING,
and a combination of wcscpy_s plus wcsncat_s altogether with the _TRUNCATE constant.

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

Patrice Terrier

#11
Version 3.00

has been released here.

The whole code has been reworked to produce an amazing code size reduction from 91 down to 14 KB !!!

Credit given to Fred and James  8)
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Carlo Pagani

Hey Patrice

How do you register on the ObjReader site?

Patrice Terrier

Carlo

Read this.
http://www.objreader.com/index.php?topic=5.0

Or send me your current email, via private message from this forum.
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

#14
If you want to download zTrace 3.00 64-bit, without registering onto my private forum (www.objreader.com)
then you can download the full VS 2017 community version from codeproject here:
https://www.codeproject.com/Articles/1183063/zTrace-for-bit-only

By the way with only 14Kb, it could be used to debug any unicode 64-bit application, whatever the language being used, with EXPLICIT linking.

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