Author Topic: zTrace 2.02 (C/C++ version 32/64-bit)  (Read 6755 times)

0 Members and 1 Guest are viewing this topic.

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
zTrace 2.02 (C/C++ version 32/64-bit)
« on: May 06, 2013, 05:50:36 PM »
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:

Code: [Select]
//+--------------------------------------------------------------------------+
//|                                                                          |
//|                               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)
« Last Edit: December 14, 2014, 07:36:40 PM by Patrice Terrier »
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
zTrace updated to version 2.01
« Reply #1 on: December 05, 2013, 04:56:07 PM »
James--

Be happy, i have added printing support to zTrace:
Quote
         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;



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

#define long_proc typedef long (__stdcall *zProc)
Quote
long 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.
« Last Edit: December 05, 2013, 05:56:46 PM by Patrice Terrier »
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
zTrace 2.01 on CodeProject
« Reply #2 on: December 07, 2013, 05:27:52 PM »
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

Offline James C. Fuller

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 662
Re: zTrace 2.01 (C/C++ version 32/64-bit)
« Reply #3 on: December 12, 2014, 05:58:40 PM »
Patrice,
  Has there been an update. I notice it is a year old and you are always tinkering :)

James

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
Re: zTrace 2.01 (C/C++ version 32/64-bit)
« Reply #4 on: December 13, 2014, 05:53:20 PM »
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.

...
« Last Edit: December 13, 2014, 06:51:23 PM by Patrice Terrier »
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
Re: zTrace 2.02 (C/C++ version 32/64-bit)
« Reply #5 on: December 14, 2014, 11:36:40 AM »
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

Offline James C. Fuller

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 662
Re: zTrace 2.02 (C/C++ version 32/64-bit)
« Reply #6 on: December 14, 2014, 03:19:08 PM »
Patrice,
  Thank you for the update of the most used tool in my toolbox.

James

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
Re: zTrace 2.02 (C/C++ version 32/64-bit)
« Reply #7 on: December 14, 2014, 07:47:52 PM »
Quote
Thank you for the update of the most used tool in my toolbox.
cool 8)

...
« Last Edit: December 14, 2014, 07:51:15 PM by Patrice Terrier »
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Offline James C. Fuller

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 662
Re: zTrace 2.02 (C/C++ version 32/64-bit)
« Reply #8 on: June 22, 2016, 11:19:57 PM »
Patrice,
  The debug.txt file is not an ascii text file on Windows 10.

James

Offline James C. Fuller

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 662
Re: zTrace 2.02 (C/C++ version 32/64-bit)
« Reply #9 on: June 24, 2016, 05:06:59 PM »
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


Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
Re: zTrace 2.02 (C/C++ version 32/64-bit)
« Reply #10 on: June 26, 2016, 02:25:56 PM »
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

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
zTrace version 3.00 64-bit
« Reply #11 on: April 18, 2017, 08:26:40 PM »
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)
« Last Edit: April 18, 2017, 08:29:17 PM by Patrice Terrier »
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Offline Carlo Pagani

  • Jr. Member
  • **
  • Posts: 62
Re: zTrace 2.02 (C/C++ version 32/64-bit)
« Reply #12 on: April 20, 2017, 12:10:51 PM »
Hey Patrice

How do you register on the ObjReader site?

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
Re: zTrace 2.02 (C/C++ version 32/64-bit)
« Reply #13 on: April 20, 2017, 12:53:55 PM »
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

Offline Patrice Terrier

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2382
  • Gender: Male
    • www.zapsolution.com
zTrace 3.00 64-bit is also on codeproject
« Reply #14 on: April 21, 2017, 12:07:11 PM »
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.

...
« Last Edit: April 21, 2017, 12:13:00 PM by Patrice Terrier »
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com