Powerbasic Museum 2020-B

IT-Consultant: Patrice Terrier => C++ programming (SDK style) => Topic started by: Patrice Terrier on January 24, 2017, 10:41:13 AM

Title: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: Patrice Terrier on January 24, 2017, 10:41:13 AM
Here is my 30Kb C++ 64-bit UNICODE version of the PowerBASIC Address demo.

All the hassle of dynamic memory allocation is done by using hidden memory LISTBOX,
using the OS built-in API to perform:
- add
- insert
- delete
- replace
- find
- sort
This could be extended to manipulate any database record structure, working with row and column.

Note: I have not checked everything thoroughly, because my main goal was to show you another {and easy} way to simulate array allocation/manipulation.
The beauty of this concept is that it can be used the same with any programming language  8)

...
Title: Re: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: James C. Fuller on January 24, 2017, 01:40:14 PM
Patrice,
  Impressive. I do like the individual listboxes as a data base cols. A little more overhead in deleting a record but not too bad.

James
Title: Re: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: James C. Fuller on January 24, 2017, 02:12:44 PM
Patrice,
  This trims the text in your FindDialogProc ????

    wcscpy(gP.findtext, gP.findtext);

James
Title: Re: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: Patrice Terrier on January 24, 2017, 02:17:49 PM
QuoteImpressive. I do like the individual listboxes as a data base cols.
indeed a good replacement for the use of VECTOR working very well with TCLib.
And fast too...
Title: Re: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: Patrice Terrier on January 24, 2017, 02:24:56 PM
Quotewcscpy(gP.findtext, gP.findtext);
Forget to remove it, i do not need triming myself.
However if you want it, my own new TRIM {any} functions are into Tools.h.


WCHAR* RTRIM$(IN WCHAR* sBuf, IN WCHAR* sChar) {
    long nLength = (long) wcslen(sBuf);
    long nLen = (long) wcslen(sChar);
    if ((nLength) && (nLen)) {
        while (nLength > 0) {
            nLength -= 1;
            if (find_wchar(sChar, &sBuf[nLength]) > -1) {
                sBuf[nLength] = L'\0';
            } else {
                break;
            }
        }
    }
    return sBuf;
}

WCHAR* LTRIM$(IN WCHAR* sBuf, IN WCHAR* sChar) {
    reverse(sBuf, wcslen(sBuf));
    sBuf = RTRIM$(sBuf, sChar);
    reverse(sBuf, wcslen(sBuf));
    return sBuf;
}

WCHAR* TRIM$(IN WCHAR* sBuf, IN WCHAR* sChar) {
    return LTRIM$(RTRIM$(sBuf, sChar), sChar);
}
Title: Re: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: Patrice Terrier on January 27, 2017, 10:49:36 AM
James--

I just checked the print funcion, and it works fine by me  ::)
Title: Re: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: James C. Fuller on January 27, 2017, 01:42:01 PM
Patrice,
  I know you said you are not finished but your print routine is not really in the spirit of the port from PB :)
Your's does not print here, but mine adapted from Fred's post:
http://www.jose.it-berater.org/smfforum/index.php?topic=5182.msg22306#msg22306
prints fine and the output is the same as the PB version.

I tried your exe and then I rebuilt the project and it still fails.
Your "successful print msgbox" pops up immediately
I do get a print tray icon with 0 documents pending that eventually goes away.
It is a network printer if that makes any difference?
Win10 64.

James


Title: Re: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: Patrice Terrier on January 27, 2017, 03:21:31 PM
Mine is also a network printer (EPSON XP-820) shared through my NAS SYNOLOGY via the USB port, and that works well by me.
I can even access it from my ANDROID tablet, my phone-book, and my SAMSUNG SMART TV.  :-[

By the way it could even be used to print/save within an image.
And should produce smaller code size than the one used in PB.

Note: the code you are refering to is written in PowerBASIC not in C++.
and perhaps your printer doesn't support the use of StretchDIBits .
Would be interesting to use zTrace to figure what part of the code fails with your config.

...
Title: Re: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: James C. Fuller on January 27, 2017, 04:21:02 PM
Patrice,
  My printer is an HP Officejet Pro 8100.
There are only 2 assignments for nRet. At the dimensioning nRet = 0 and at the nRet = StretchDIBits(.....
I added if (nRet == GDI_ERROR) nRet = 0; right after and it still fails??

This is my interpretation of Fred's PB code.
It makes heavy use of Fred's String class and uses my version of aedynarray.h.

James


int PrintRecord (HWND hWnd, AddressTypeArray&  AddArray, int Index)
{
    fstring  fsRec;
    fstring  fsBuffer;
    HFONT    hFont = {0};
    HFONT    hOldFont = {0};
    TEXTMETRIC  tm = {0};
    int      xChar = {0};
    int      yChar = {0};
    int      xPage = {0};
    int      yPage = {0};
    int      i = {0};
    int      iLineCount = {0};
    int      iCharsCopied = {0};
    DWORD    dwBytes = 128;
    DWORD    nBufferSize = 1024;
    DWORD*   dwPtr;
    DWORD    dwWord = {0};
    RECT     rc = {0};
    HDC      hdcPrn = {0};
    DOCINFO  di = {sizeof(DOCINFO), _T("Print1: Printing")};
    HWND     hCtl = {0};
    fsBuffer.Make(0, nBufferSize);
    GetDefaultPrinter(fsBuffer.lpStr(), &dwBytes);
    hdcPrn = CreateDC( NULL, fsBuffer.lpStr(), NULL, NULL);
    if(hdcPrn == NULL )
    {
        return -1;
    }
    hFont = CreateFont(- 1 * ( 15 * GetDeviceCaps( hdcPrn, LOGPIXELSY)) / 72, 0, 0, 0, FW_HEAVY, 0, TRUE, 0, 0, 0, 0, 0, 0, _T("Ariel"));
    fsRec.Make(0, 32);
    GetWindowText(GetDlgItem(hWnd, IDC_INDEX), fsRec.lpStr(), fsRec.Len());
    fstring  fs(_T("Address Book, Record "));
    fs += fsRec;
    xPage = GetDeviceCaps( hdcPrn, HORZRES);
    yPage = GetDeviceCaps( hdcPrn, VERTRES);
    if(StartDoc(hdcPrn, &di) > 0 )
    {
        if(StartPage(hdcPrn) > 0 )
        {
            hOldFont = ( HFONT) SelectObject( hdcPrn, hFont);
            GetTextMetrics(hdcPrn, &tm);
            yChar = tm.tmHeight + tm.tmExternalLeading;
            xChar = tm.tmAveCharWidth;
            rc.top = 200;
            rc.bottom = rc.top + yChar;
            rc.left = 0;
            rc.right = xPage;
            DrawText(hdcPrn, fs.lpStr(), -1, &rc, DT_CENTER);
            DeleteObject(SelectObject(hdcPrn, hOldFont));
            hFont = CreateFont(- 1 * ( 11 * GetDeviceCaps( hdcPrn, LOGPIXELSY)) / 72, 0, 0, 0, FW_HEAVY, 0, 0, 0, 0, 0, 0, 0, 0, _T("Ariel"));
            hOldFont = ( HFONT) SelectObject( hdcPrn, hFont);
            GetTextMetrics(hdcPrn, &tm);
            yChar = tm.tmHeight + tm.tmExternalLeading + 20;
            xChar = tm.tmAveCharWidth;
            TextOut(hdcPrn, 300, 600, _T("Company:"), 8);
            TextOut(hdcPrn, 300, 600 + 1 * yChar, _T("Name:"), 5);
            TextOut(hdcPrn, 300, 600 + 3 * yChar, _T("Address:"), 8);
            TextOut(hdcPrn, 300, 600 + 4 * yChar, _T("City:"), 5);
            TextOut(hdcPrn, 300, 600 + 5 * yChar, _T("State/Prov:"), 11);
            TextOut(hdcPrn, 300, 600 + 6 * yChar, _T("Zip/Postal:"), 11);
            TextOut(hdcPrn, 300, 600 + 7 * yChar, _T("Country:"), 8);
            TextOut(hdcPrn, 300, 600 + 9 * yChar, _T("Phone:"), 6);
            TextOut(hdcPrn, 300, 600 + 10 * yChar, _T("Fax:"), 4);
            TextOut(hdcPrn, 300, 600 + 11 * yChar, _T("Email:"), 6);
            TextOut(hdcPrn, 300, 600 + 12 * yChar, _T("Url:"), 4);
            TextOut(hdcPrn, 300, 600 + 14 * yChar, _T("Comments:"), 9);
            DeleteObject(SelectObject(hdcPrn, hOldFont));
            fsBuffer = AddArray[Index].Company;
            TextOut(hdcPrn, 1000, 600, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer = AddArray[Index].FirstName;
            fsBuffer += _T(" ");
            fsBuffer += AddArray[Index].LastName;
            TextOut(hdcPrn, 1000, 600 + 1 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer = AddArray[Index].Address1;
            TextOut(hdcPrn, 1000, 600 + 3 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer = AddArray[Index].CityName;
            TextOut(hdcPrn, 1000, 600 + 4 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer = AddArray[Index].StateName;
            TextOut(hdcPrn, 1000, 600 + 5 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer = AddArray[Index].ZipCode;
            TextOut(hdcPrn, 1000, 600 + 6 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer.Make(0, 128);
            hCtl = GetDlgItem( hWnd, IDC_COUNTRY);
            GetWindowText(hCtl, fsBuffer.lpStr(), 128);
            TextOut(hdcPrn, 1000, 600 + 7 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer = AddArray[Index].Phone;
            TextOut(hdcPrn, 1000, 600 + 9 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer = AddArray[Index].Fax;
            TextOut(hdcPrn, 1000, 600 + 10 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer = AddArray[Index].Email;
            TextOut(hdcPrn, 1000, 600 + 11 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            fsBuffer = AddArray[Index].Url;
            TextOut(hdcPrn, 1000, 600 + 12 * yChar, fsBuffer.lpStr(), fsBuffer.Len());
            hCtl = GetDlgItem( hWnd, IDC_COMMENTS);
            iLineCount = SendMessage( hCtl, ( UINT) EM_GETLINECOUNT, ( WPARAM) 0, ( LPARAM) 0);
            fsBuffer.Make(0, 1024);
            dwPtr = ( DWORD*) fsBuffer.lpStr();
            for(i = 0; i <= iLineCount - 1; i += 1)
            {
                *dwPtr = MAKELONG( 1024, 0);
                iCharsCopied = SendMessage( hCtl, ( UINT) EM_GETLINE, ( WPARAM) i, ( LPARAM) fsBuffer.lpStr());
                TextOut(hdcPrn, 1000, 600 + (15 + i)*yChar, fsBuffer.lpStr(), iCharsCopied);
            }

            if(EndPage(hdcPrn) > 0 )
            {
                EndDoc(hdcPrn);
            }
        }
    }
    DeleteDC(hdcPrn);
    return 0;
}

Title: Re: C++ 64-bit Address (with LISTBOX dynamic memory allocation)
Post by: Patrice Terrier on January 27, 2017, 04:33:46 PM
The beauty of WM_PRINT is that is performs a hard copy of the client area, and Windows once again, does most of the work for us, helping to produce smaller code size, and that was my goal  :)