The MASM Forum

General => The Campus => Topic started by: xandaz on December 18, 2020, 06:12:07 AM

Title: Printing operation
Post by: xandaz on December 18, 2020, 06:12:07 AM
i took this code from a siteHANDLE hdl;
DEVMODE* devmode;
OpenPrinter(L"HP Deskjet F4400 series", &hdl, NULL);
int size = DocumentProperties(NULL, hdl, L"HP Deskjet F4400 series", NULL, NULL, 0);
devmode = (DEVMODE*)malloc(size);
DocumentProperties(NULL, hdl, L"HP Deskjet F4400 series", devmode, NULL, DM_OUT_BUFFER);
HDC printerDC = CreateDC(L"WINSPOOL", devmode->dmDeviceName, NULL, devmode);
DOCINFO info;
memset(&info, 0, sizeof(info));
info.cbSize = sizeof(info);
StartDoc(printerDC, &info);
StartPage(printerDC);
Rectangle(printerDC, 100, 100, 200, 200);
EndPage(printerDC);
EndDoc(printerDC);
DeleteDC(printerDC);


and translated it into this:
.if ax==IDB_BUTTON

invoke PrintDlg,addr prndlg
invoke SendMessage,hEdit,WM_SETTEXT,0,addr devmode.dmDeviceName
invoke OpenPrinter,addr szPrinterName,addr hPrinter,NULL
mov eax,rv(DocumentProperties,hWnd,hPrinter,addr szPrinterName,NULL,NULL,0)
invoke DocumentProperties,hWnd,hPrinter,addr szPrinterName,addr devmode,0,DM_OUT_BUFFER
invoke CreateDC,addr hService,addr devmode.dmDeviceName,NULL,addr devmode
mov prndlg.hDC,eax
mov hDC,eax
invoke StartDoc,prndlg.hDC,addr dci
invoke StartPage,prndlg.hDC
invoke Rectangle,prndlg.hDC,100,100,200,200
invoke EndPage,prndlg.hDC
invoke EndDoc,prndlg.hDC
invoke DeleteDC,prndlg.hDC
.endif


but nothing happens. The devmode.dmDeviceName doesn't change when PrintDlg is called. Can anyonw give some insight into this?
Title: Re: orinting operation
Post by: TimoVJL on December 18, 2020, 06:38:25 AM
If you use PrintDlg, you can use hdc from it., PD_RETURNDC
https://docs.microsoft.com/fi-fi/windows/win32/api/commdlg/ns-commdlg-printdlga?redirectedfrom=MSDN

https://docs.microsoft.com/en-us/windows/win32/dlgbox/using-common-dialog-boxes
Title: Re: orinting operation
Post by: xandaz on December 18, 2020, 07:53:29 AM
   thanks Timo
Title: Re: orinting operation
Post by: xandaz on December 20, 2020, 06:06:42 AM
    PRINTDLG.hDevMode doesn't return the printer name. Why would that be? does anyone have an example of this? Thanks
Title: Re: orinting operation
Post by: xandaz on December 21, 2020, 03:09:07 AM
   so...i lost my faith with PrintDlg and got into EnumPrinters instead. Does anyone know how to get the icon corresponding to each printer? i thought it would be PRINTER_INFO_1 but it didn't work. Can someone give me a hand? thanks
Title: Re: orinting operation
Post by: TouEnMasm on December 21, 2020, 03:40:34 AM

Icon are found in the resource of axecute files,dll...
If you know the full path of the printer,perhaps you can extract the icon of the resource.
Title: Re: orinting operation
Post by: TimoVJL on December 21, 2020, 04:22:24 AM
PrintDlg
https://www.codeproject.com/Articles/764057/GDI-Drawing-and-Printing
void GDIDraw::Print(HWND hWnd)
{
   PRINTDLG pd = {0};
   pd.lStructSize = sizeof( pd );
   pd.hwndOwner = hWnd;
   pd.Flags = PD_RETURNDC;
   
   // Retrieves the printer DC
   if (PrintDlg(&pd))
   {
      HDC hdc = pd.hDC;
      StartDoc (hdc, &di);
      StartPage (hdc);   
 
      // Drawing code begin
      //   
      RECT rc;
      rc.top = 100;
      rc.left = 100;
      rc.bottom = 300;
      rc.right = 300;

      HBRUSH greenBrush=CreateSolidBrush(RGB(0,255,0));
      FillRect(hdc, &rc, greenBrush);
      DeleteObject(greenBrush);
      //
      // Drawing code end

      EndPage (hdc);
      EndDoc(hdc);
      DeleteObject(hdc);
   }
}
Title: Re: orinting operation
Post by: xandaz on December 21, 2020, 04:30:30 AM
   Thanks guys, it's been helpfull. ty :thumbsup:
Title: Re: orinting operation
Post by: xandaz on December 21, 2020, 04:45:23 AM
   What i trully meant was where the hell does PrinDlg get it's icons?
Title: Re: orinting operation
Post by: xandaz on December 22, 2020, 05:21:37 AM
   Timo. Thanks for the input, but, your code doesn't work. The document shows in the printer tray but it remains there unoperational. It doesn't print.
invoke StartDoc,prndlg.hDC,addr dci
invoke StartPage,prndlg.hDC
invoke CreateSolidBrush,0ffh
mov obj,eax
invoke SelectObject,prndlg.hDC,eax
invoke FillRect,prndlg.hDC,addr rect,obj
; invoke Rectangle,prndlg.hDC,100,100,200,200
invoke EndPage,prndlg.hDC
invoke EndDoc,prndlg.hDC
invoke DeleteObject,obj
Title: Re: orinting operation
Post by: TimoVJL on December 22, 2020, 06:24:18 AM
A test program that works in my PC
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commdlg.h>

void GDIDraw_Print(HWND hWnd)
{
   PRINTDLG pd = {0};
   pd.lStructSize = sizeof( pd );
   pd.hwndOwner = hWnd;
   pd.Flags = PD_RETURNDC;
   
   // Retrieves the printer DC
   if (PrintDlg(&pd))
   {
      HDC hdc = pd.hDC;
      StartDoc (hdc, NULL);
      StartPage (hdc);   

      // Drawing code begin
      //   
      RECT rc;
      rc.top = 100;
      rc.left = 100;
      rc.bottom = 300;
      rc.right = 300;

      HBRUSH greenBrush=CreateSolidBrush(RGB(0,255,0));
      FillRect(hdc, &rc, greenBrush);
      DeleteObject(greenBrush);
      //
      // Drawing code end

      EndPage (hdc);
      EndDoc(hdc);
      DeleteObject(hdc);
   }
}

void __cdecl WinMainCRTStartup(void)
{
GDIDraw_Print(0);
ExitProcess(0);
}
Title: Re: Printing operation
Post by: xandaz on December 22, 2020, 11:58:22 PM
   Timo. Thanks. your little app didn't work on my end.
Title: Re: Printing operation
Post by: jj2007 on December 23, 2020, 12:52:32 AM
Do the RichMasm and qEditor print dialogs work on your machine? Both are invoked with Ctrl P
Title: Re: Printing operation
Post by: xandaz on December 23, 2020, 01:02:35 AM
   Yes. They're working. The document stays stalled i n printer tray and nothig happens. If I write it to PDF, it works. Thanks
Title: Re: Printing operation
Post by: xandaz on December 23, 2020, 03:44:23 AM
   Finally got it to work. Unmentioning an output file for the DOCINFO struct did the work.
Title: Re: Printing operation
Post by: xandaz on December 24, 2020, 06:57:24 AM
    Hi guys. I wonder why it is that the devmode.dmDeviceName doesn't return the printer chosen. does anyone know? thanks
Title: Re: Printing operation
Post by: deeR44 on December 24, 2020, 06:15:29 PM
I'll never get used to finding stuff like the following in a MASM forum:

void GDIDraw::Print(HWND hWnd)
{
   PRINTDLG pd = {0};
   pd.lStructSize = sizeof( pd );
   pd.hwndOwner = hWnd;
   pd.Flags = PD_RETURNDC;
   
   // Retrieves the printer DC
   if (PrintDlg(&pd))
   {
      HDC hdc = pd.hDC;
      StartDoc (hdc, &di);
      StartPage (hdc);   
.
.
.
Title: Re: Printing operation
Post by: TimoVJL on December 24, 2020, 09:51:41 PM
Quote from: xandaz on December 24, 2020, 06:57:24 AM
    Hi guys. I wonder why it is that the devmode.dmDeviceName doesn't return the printer chosen. does anyone know? thanks
A hint for that:
void ShowPrnInfo(PRINTDLG *pd)
{
LPDEVMODE devmode = (LPDEVMODE)GlobalLock(pd->hDevMode);
LPDEVNAMES devnames = (LPDEVNAMES)GlobalLock(pd->hDevNames);
LPCTSTR driver = (LPCTSTR)devnames + devnames->wDriverOffset;
LPCTSTR device = (LPCTSTR)devnames + devnames->wDeviceOffset;
LPCTSTR output = (LPCTSTR)devnames + devnames->wOutputOffset;
printf("%s\n", driver);
printf("%s\n", device);
printf("%s\n", output);
GlobalUnlock(pd->hDevNames);
GlobalUnlock(pd->hDevMode);
}
Title: Re: Printing operation
Post by: xandaz on December 26, 2020, 10:06:59 AM
    Hi again. I've been looking into printing text documents. I used WritePrinter but it doesn't work. GetLastError gives ERROR_NO_START_DOC, but the StartDoc Function gives no error. The Printer just pushes the sheet and it comes out blank on the other side. Is there a simple way to print document files? Thanks
Title: Re: Printing operation
Post by: TimoVJL on December 26, 2020, 10:33:45 AM
 Did you use StartDocPrinter function?

EDIT: DrawText[Ex] if good for printing plain text usind HDC.
Title: Re: Printing operation
Post by: xandaz on December 26, 2020, 11:22:43 PM
   i have the following code: invoke PrintDlg,addr prndlg
invoke OpenPrinter,addr szPrinterName,addr hPrinter,0;addr prndef
invoke LocalAlloc,LMEM_FIXED,0ffffh
mov lpBuffer,eax
invoke SendMessage,hEdit,WM_GETTEXT,0ffffh,lpBuffer
invoke StartDocPrinter,hPrinter,1,addr dci
invoke StartPagePrinter,hPrinter
invoke WritePrinter,hPrinter,lpBuffer,0ffffh,addr BytesWritten
invoke EndPagePrinter,hPrinter
invoke EndDocPrinter,hPrinter
invoke ClosePrinter,hPrinter
.endif

...that doesn't work. The document shows as being printed in the printer's tray but then it disappears. Thanks
Title: Re: Printing operation
Post by: xandaz on December 26, 2020, 11:53:23 PM
   i also tried EM_STERAMOUT but it doesn't work either. bollocks. :thdn:
Title: Re: Printing operation
Post by: jj2007 on December 27, 2020, 12:04:43 AM
GuiParas equ "Printing from a RichEdit control", w300, h200
include \masm32\MasmBasic\Res\MbGui.asm
GuiControl MyEdit, "RichEdit", "Select some text and hit Control P"
Event Key
  If_ VKey==VK_P || VKey==-VK_P Then <MsgBox 0, Str$("%i pages printed", PrintRtf(hMyEdit, 2)), "PrintRtf:", MB_OK>
GuiEnd
Title: Re: Printing operation
Post by: TimoVJL on December 27, 2020, 12:17:29 AM
 How to Print the Contents of Rich Edit Controls (https://docs.microsoft.com/en-us/windows/win32/controls/printing-rich-edit-controls)
Title: Re: Printing operation
Post by: xandaz on December 27, 2020, 12:19:47 AM
   Thanks guys. You're the best always.  :thumbsup:
Title: Re: Printing operation
Post by: xandaz on December 27, 2020, 12:32:16 AM
   JJ. Some code would be alright to show. Is it embeded in the executable?
Title: Re: Printing operation
Post by: hutch-- on December 27, 2020, 12:50:35 AM
I wrote this over 10 years ago and it the print algo in QE but its part of a more complicated method. It may be useful to you.

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

edit_print proc parent:DWORD,edit:DWORD,instance:DWORD

    LOCAL wTwip         :DWORD
    LOCAL hTwip         :DWORD
    LOCAL mLeft         :DWORD
    LOCAL mTop          :DWORD
    LOCAL mRight        :DWORD
    LOCAL mBottom       :DWORD
    LOCAL szPrint       :DWORD
    LOCAL hRes          :DWORD
    LOCAL vRes          :DWORD
    LOCAL hppli         :DWORD
    LOCAL vppli         :DWORD
    LOCAL pd            :PRINTDLG
    LOCAL fr            :FORMATRANGE
    LOCAL dinf          :DOCINFO
    LOCAL cr            :CHARRANGE

    push ebx
    push esi
    push edi

    sas szPrint,"Print"

    invoke SendMessage,edit,EM_FORMATRANGE,FALSE,NULL

  ; ------------------------
  ; zero fill the structures
  ; ------------------------
    invoke charfill,ADDR pd,SIZEOF PRINTDLG,0
    invoke charfill,ADDR fr,SIZEOF FORMATRANGE,0
    invoke charfill,ADDR dinf,SIZEOF DOCINFO,0

    mov pd.lStructSize, SIZEOF pd
    mrm pd.hwndOwner,   parent
    mov pd.Flags,       PD_RETURNDC or PD_NOPAGENUMS or PD_PRINTSETUP
    mrm pd.hInstance,   instance

  ; ------------------
  ; half inch in TWIPS
  ; ------------------
    mov mLeft,      720         ; left   margin
    mov mTop,       720         ; top    margin
    mov mRight,     720         ; right  margin
    mov mBottom,    720         ; bottom margin

    ; -----------------------------------------------

    .if rv(PrintDlg,ADDR pd)
      invoke SetCursor,rv(LoadCursor,NULL,IDC_WAIT)

      mov hRes, rv(GetDeviceCaps,pd.hDC,HORZRES)            ; horizontal resolution
      mov vRes, rv(GetDeviceCaps,pd.hDC,VERTRES)            ; vertical resolution

      mov hppli, rv(GetDeviceCaps,pd.hDC,LOGPIXELSX)        ; horizontal pixels per logical inch
      mov vppli, rv(GetDeviceCaps,pd.hDC,LOGPIXELSY)        ; vertical pixels per logical inch

      mov esi, rv(IntDiv,hRes,hppli)
      mov wTwip, rv(IntMul,esi,1440)                        ; calculate width

      mov esi, rv(IntDiv,vRes,vppli)
      mov hTwip, rv(IntMul,esi,1440)                        ; calculate height

      mrm fr.hdc,           pd.hDC
      mrm fr.hdcTarget,     pd.hDC

      mrm fr.rcPage.left, mLeft
      mrm fr.rcPage.top, mTop

      mrm fr.rcPage.right, wTwip
      mov eax, mRight
      sub fr.rcPage.right, eax

      mrm fr.rcPage.bottom, hTwip
      mov eax, mBottom
      sub fr.rcPage.bottom, eax

      mrm fr.rc.left, mLeft
      mrm fr.rc.top, mTop
      mrm fr.rc.right, fr.rcPage.right
      mrm fr.rc.bottom, fr.rcPage.bottom

    ; ------------------------
    ; whole document selection
    ; ------------------------
      mov fr.chrg.cpMin, 0
      mov fr.chrg.cpMax, -1
      invoke SendMessage,edit,EM_EXSETSEL,0,ADDR fr.chrg
      invoke SendMessage,edit,EM_EXGETSEL,0,ADDR fr.chrg

    ; -----------------------------------------------

      mov dinf.cbSize,      SIZEOF dinf
      mrm dinf.lpszDocName, szPrint
      mov dinf.lpszOutput,  NULL

      invoke StartDoc,pd.hDC,ADDR dinf

  ; ******************************

    print_loop:
      invoke StartPage,pd.hDC
      mov esi, rv(SendMessage,edit,EM_FORMATRANGE,TRUE,ADDR fr)
      cmp esi, fr.chrg.cpMax
      jge outp
      mov fr.chrg.cpMin,esi
      invoke EndPage,pd.hDC
      jmp print_loop
    outp:

  ; ******************************

      invoke SendMessage,edit,EM_FORMATRANGE,FALSE,NULL
      invoke EndPage, pd.hDC
      invoke EndDoc,  pd.hDC
      invoke DeleteDC,pd.hDC

      invoke SetCursor,rv(LoadCursor,NULL,IDC_ARROW)

      mov eax, 1
    .endif

    ; -----------------------------------------------

    pop edi
    pop esi
    pop ebx

    ret

edit_print endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
Title: Re: Printing operation
Post by: jj2007 on December 27, 2020, 01:35:54 AM
Quote from: xandaz on December 27, 2020, 12:32:16 AM
   JJ. Some code would be alright to show. Is it embeded in the executable?

The source is what you see above - see PrintRTF (http://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1400). I guess you are curious what's under the hood - here it is.
Title: Re: Printing operation
Post by: xandaz on December 27, 2020, 01:42:05 AM
   Hi. Are you sure it can't be done like this:
.elseif uMsg==WM_COMMAND
mov eax,wParam
.if ax==IDB_BUTTON

invoke OpenPrinter,addr szPrinterName,addr hPrinter,0; addr prndef
invoke StartDocPrinter,hPrinter,1,addr dci
invoke StartPagePrinter,hPrinter
m2m EditStream.dwCookie,hPrinter
mov EditStream.pfnCallback,offset StreamOutProc
invoke SendMessage,hEdit,EM_STREAMOUT,SF_RTF,addr EditStream
invoke EndPagePrinter,hPrinter
invoke EndDocPrinter,hPrinter
invoke ClosePrinter,hPrinter
.endif
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret

WndProc endp

StreamOutProc PROC dwCookie:DWORD,pbBuff:DWORD,cb:DWORD,pcb:DWORD
invoke WriteFile,dwCookie,pbBuff,cb,pcb,0
xor eax,eax
ret
StreamOutProc endp
end start


Well it's not working but it appears in the printers tray and then it's gone
Title: Re: Printing operation
Post by: TimoVJL on December 27, 2020, 02:38:44 AM
As HP Deskjet F4400 series use PCL3 GUI printer language, a direct printing might be a broblem.
http://www.verypdf.com/wordpress/201107/what-is-pcl3gui-format-1195.html

An old C code for text only printing with normal printer driver.
int OnPrint(HWND hWnd) {
DOCINFO di;
TEXTMETRIC tm;
int i,j,x,y,mx,my,ir;
RECT rc;
unsigned char szBuf[256];

j = SendMessage(hWndEdit, EM_GETLINECOUNT, 0, 0);
//if (!j) return 0;
memset(&pd, 0, sizeof(PRINTDLG));
pd.lStructSize = sizeof(PRINTDLG);
pd.hwndOwner = hWndFrame;
pd.hInstance = hInst;
pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE;
if (PrintDlg(&pd)) {
bUserAbort = FALSE;
hDlgPrint = CreateDialog(hInst, MAKEINTRESOURCE(1001), hWnd, PrintDlgProc);
SetAbortProc(pd.hDC, AbortProc);

memset(&di, 0, sizeof(di));
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = szFileTitle;
mx = GetDeviceCaps(pd.hDC, HORZRES);
my = GetDeviceCaps(pd.hDC, VERTRES);
y = psd.rtMargin.top / 4;
x = psd.rtMargin.left / 4;
if (StartDoc(pd.hDC, &di)) {
StartPage(pd.hDC);
GetTextMetrics(pd.hDC, &tm);
for (i=0;i<j;i++) {
szBuf[0] = 255; szBuf[1] = 0;
ir = SendMessage(hWndEdit, EM_GETLINE, i, (LPARAM)&szBuf);
if (ir>0) {
rc.left = x; rc.top = y;
rc.right = mx; rc.bottom = my;
szBuf[ir] = 0;
ir = DrawText(pd.hDC, (LPSTR)&szBuf, ir, &rc,
DT_WORDBREAK | DT_EXPANDTABS);
y += ir;
} else y += tm.tmHeight;
if ((y+tm.tmHeight)>my) {
y = psd.rtMargin.top / 4;
EndPage(pd.hDC);
StartPage(pd.hDC);
}
}
EndPage(pd.hDC);
if (EndDoc(pd.hDC) <= 0) {
LoadString(hInst, IDR_PRINTERROR, szBuf, sizeof(szBuf));
MessageBox(hWndFrame, szBuf, szAppName, MB_OK);
}
if (!bUserAbort)
{
EnableWindow(hWnd, TRUE);
DestroyWindow(hDlgPrint);
}
}
}
if (pd.hDC)
DeleteDC(pd.hDC);
if (pd.hDevMode) GlobalFree(pd.hDevMode);
if (pd.hDevNames) GlobalFree(pd.hDevNames);

return 0;
}

UPDATE:...
if (pd.hDevMode) GlobalFree(pd.hDevMode);
if (pd.hDevNames) GlobalFree(pd.hDevNames);
...
Title: Re: Printing operation
Post by: jj2007 on December 27, 2020, 04:20:33 AM
Quote from: xandaz on December 27, 2020, 01:42:05 AM
   Hi. Are you sure it can't be done like this:

There are apparently several ways to print from a richedit control. Mine works fine.
Title: Re: Printing operation
Post by: xandaz on December 27, 2020, 06:56:35 AM
   Yeah JJ. Your way seems to work fine. The problem is that your code is too complex for my peanut-sized mind. Thanks anyway
Title: Re: Printing operation
Post by: jj2007 on December 27, 2020, 08:05:21 AM
I can't help you much because I did this almost 4 years ago and have forgotten the details. However, StartDoc, StartPage, EndPage, EndDoc and the EM_FORMATRANGE message are all well documented... maybe the source posted by Hutch (http://masm32.com/board/index.php?topic=9033.msg99298#msg99298) is clearer.