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)
...
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
Patrice,
This trims the text in your FindDialogProc ????
wcscpy(gP.findtext, gP.findtext);
James
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...
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);
}
James--
I just checked the print funcion, and it works fine by me ::)
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
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.
...
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;
}
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 :)