How do I send the contents of a view to a printer?
One other problem. I can create 3D toolbar buttons OK but when I check hasFlatAppearence the toolbar background goes white. The backColor is set to COLOR_3DFACE so this shouldn't happen. Any ideas? Where can I get basic questions answered? Is there a book (apart from Ted Bracht's)? Peter Simmonds Northampton, UK |
Peter,
> How do I send the contents of a view to a printer? Can you give a bit more detail about what you want to print, text/graphics/a mixture of the two/code from a workspace/a "print screen" emulation .... > One other problem. I can create 3D toolbar buttons OK but when I > check hasFlatAppearence the toolbar background goes white. The > backColor is set to COLOR_3DFACE so this shouldn't happen. > Any ideas? There are a couple of ways that seem to work but it's a bit of a black art and I don't really know the "correct" way. 1) Set the backcolour for the Shell to COLOR_3DFACE as well. This is the method I tend to use as the Shell's background is usually covered by other subviews. 2) Set the #isTransparent aspect of the Toolbar to true. I've no idea why this works, it seems to me to be the wrong way round.... > Where can I get basic questions answered? Is there a book > (apart from Ted Bracht's)? No other books, as far as I know. Asking here (or looking through the newsgroup archive), trial-and-error using a workspace and browsing the image are the ways I tend to work things out. -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
>
> > How do I send the contents of a view to a printer? > > Can you give a bit more detail about what you want to print, text/graphics/a > mixture of the two/code from a workspace/a "print screen" emulation .... > I want to print from a subclass of View in its onPaintRequired: method. I will have a PaintEvent to get a Canvas from so what I want to do is redirect the output of my code from the Canvas to a "printing canvas". The output will be a mixture of 2D graphics and text. Peter Simmonds Northampton, UK |
Peter Simmonds wrote:
> I want to print from a subclass of View in its onPaintRequired: method. I > will have > a PaintEvent to get a Canvas from so what I want to do is redirect the > output > of my code from the Canvas to a "printing canvas". The output will be a > mixture > of 2D graphics and text. Code like: canvas := PrinterCanvas choose ifNil: [^ self]. canvas startDocNamed: 'Hi!'; startPage. "paint code goes here" canvas endPage; endDoc. canvas free. should get you started with a Canvas that you can paint on. Be aware that the canvas will have a different resolution from the canvas that you paint on in your normal View code, so you'll have to scale the widths of your lines appropriately. I add a method to Canvas: ===================== pixelsFromDesktopPixels: aPointOrNumber "answer the given point or number scaled from the desktop resolution (ppi) to that of the reciever. A kludge for simple adaptation of features defined in terms of screen pixels to other resolutions" #CUadded. ^ self resolution / View desktop resolution * aPointOrNumber. ===================== to help with that, although it is, as the comment states, just a kludge. You will need a similar hack (or something better) in order to get the fonts scaled correctly. Windows also has lots of bells and whistles for manipulating the mapping between coordinates and actual Pixels, all of which confuse me utterly. They are not activated by default, so the mapping is 1-to-1 unless you change it yourself. (I believe that you should be able to get better results if you /do/ use the advanced mappings, but I've never had the courage to try ;-) If you want to do this properly, then the chances are that you'll want to use more of the underlying Windows printing system than is exposed in a vanilla Dolphin installation. Ian's printing goodies contain wrappers for a lot more of the API, even if you don't use all of his printing framework (which is, if I understand it correctly, oriented towards printing using the Rich Text control and so not quite what you need here.) Be prepared to waste a lot of ink ;-) I found it helpful to install a PostScript printer driver, set to print to file, and then used the Aladdin PostScript viewer (freeware) to look at the results -- it's not perfect but it has probably saved me at least one printer cartridge already. -- chris |
In reply to this post by Peter Simmonds
Peter,
> I want to print from a subclass of View in its onPaintRequired: > method. I will have > a PaintEvent to get a Canvas from so what I want to do is redirect the > output > of my code from the Canvas to a "printing canvas". The output will be > a mixture > of 2D graphics and text. I would do this by having an Object that knew how to draw itself and then passing it a canvas to draw on. Your #onPaintRequired: method would be _something_ like MyView>>onPaintRequired: aPaintEvent self model drawOn: aPaintEvent canvas and another method would print to a printer MyView>>printIt | printerCanvas | printerCanvas := PrinterCanvas choose. printerCanvas startDoc; startPage. self model drawOn: printerCanvas. printerCanvas endPage; endDoc. How and when you use the #printIt method really depends on your application and the situations in which you want a hard copy to be produced. The printer and screen canvas are going to have different capabilities, extents and resolutions for example, so your #drawOn: method will have to be able to adjust it's rendering to cope with that. As a simple example.... add the following method to the Dolphin example class ScribbleView ScribbleView>>printIt | printerCanvas | printerCanvas := PrinterCanvas choose. printerCanvas startDoc; startPage. self model do: [:each | each drawOn: printerCanvas]. printerCanvas endPage; endDoc In a workspace evaluate s := Scribble show draw a nice picture in the Scribble shell and then evaluate s view printIt -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
In reply to this post by Peter Simmonds
Thanks for your help. One last thing on printing. How can I programmatically
change the orientation of the paper. That is from Portrait to Landscape and vice versa. Peter Simmonds Northampton, UK |
In reply to this post by Chris Uppal-3
"Chris Uppal" <[hidden email]> wrote in message
news:[hidden email]... > Peter Simmonds wrote: > > > I want to print from a subclass of View in its onPaintRequired: method. I > > will have > > a PaintEvent to get a Canvas from so what I want to do is redirect the > > output > > of my code from the Canvas to a "printing canvas". The output will be a > > mixture > > of 2D graphics and text. > >... > ..... > Be prepared to waste a lot of ink ;-) I found it helpful to install a > PostScript printer driver, set to print to file, and then used the Aladdin > PostScript viewer (freeware) to look at the results -- it's not perfect but it > has probably saved me at least one printer cartridge already. If your printer driver doesn't have a preview mode (or your printer is an Epson and you don't want to use its driver because it crashes frequently requiring a machine restart to sort out), then I can recommend Fine Print. Not only does this handy utility give you a preview, but it can also pack a number of pages onto one physical page, a big saving for draft output. There is a free "trial" version which prints a small banner on each page, but this is not a problem for draft output. It doesn't cost much anyway: http://fineprint.com/products/fineprint/index.html Regards Blair |
In reply to this post by Peter Simmonds
Peter,
> Thanks for your help. One last thing on printing. How can I > programmatically change the orientation of the paper. That is from > Portrait to Landscape and vice versa. With great difficulty, unfortunately. I've extracted some code from my printer goodie that will work for the _default_ printer (you don't get a normal PrinterDialog that allows you to choose) as an example. FileIn the code between the =~=~=s, it adds some required structures and an interface method, then evaluate the following in a workspace. Changing the argument in the second section allows you to print in Portrait(1) or Landscape(2) It could probably be simplified but I wasted a lot of ink, paper and brain cells getting to this point so I tend to leave it alone. "Get a PRINTDLGEX struct for the default printer" printDlgStruct := PRINTDLGEX new. printDlgStruct ownerView: View active; flags: ("PD_RETURNDEFAULT" 1024); nCopies: 1; nStartPage: -1. ComDlgLibrary default printDlgEx: printDlgStruct asParameter. "Set the DEVMODE orientation 1=Portrait 2=Landscape" addr := KernelLibrary default globalLock: printDlgStruct hDevMode. (DEVMODE new initializeAtAddress: addr) dmOrientation: 1. KernelLibrary default globalUnlock: printDlgStruct hDevMode. "Create a PrinterCanvas for the default printer in this orientation" devModeAddr := KernelLibrary default globalLock: printDlgStruct hDevMode. devMode := DEVMODE new initializeAtAddress: devModeAddr. devNamesAddr := KernelLibrary default globalLock: printDlgStruct hDevNames. devNames := DEVNAMES new initializeAtAddress: devNamesAddr. printerDC := GDILibrary default createDC: (String fromAddress: devNamesAddr yourAddress + devNames wDriverOffset) lpszDevice: (String fromAddress: devNamesAddr yourAddress + devNames wDeviceOffset) lpszOutput: (String fromAddress: devNamesAddr yourAddress + devNames wOutputOffset) lpdvminit: devMode. KernelLibrary default globalUnlock: printDlgStruct hDevNames. KernelLibrary default globalUnlock: printDlgStruct hDevMode. pc := PrinterCanvas withOwnedDC: printerDC asInteger. "Test it" pc startDoc; startPage; text: 'This is a test' at: 100@100; endPage; endDoc. =~=~=~=~=~= "Filed out from Dolphin Smalltalk XP"! Win32Structure subclass: #DEVMODE instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: ''! DEVMODE guid: (GUID fromString: '{BC292F08-565C-4AED-AE80-7B52F463FBD1}')! DEVMODE comment: 'See [DolphinImageFolder]/Ian Bartholomew/Documentation for details (C) 2004 Ian Bartholomew [hidden email] Public Domain Freeware'! !DEVMODE categoriesForClass!External-Data-Structured-Win32!IDB Goodies! ! !DEVMODE methodsFor! dwSize: anObject "Set the receiver's dwSize field to the value of anObject." bytes wordAtOffset: 37 put: anObject! ! !DEVMODE categoriesFor: #dwSize:!**compiled accessors**!public! ! !DEVMODE class methodsFor! defineFields "Define the fields of the Win32 DEVMODE structure. DEVMODE compileDefinition DEVMODE decompileDefinition typedef struct _devicemode BCHAR dmDeviceName[CCHDEVICENAME]; WORD dmSpecVersion; WORD dmDriverVersion; WORD dmSize; WORD dmDriverExtra; DWORD dmFields; union { struct { short dmOrientation; short dmPaperSize; short dmPaperLength; short dmPaperWidth; }; POINTL dmPosition; }; short dmScale; short dmCopies; short dmDefaultSource; short dmPrintQuality; short dmColor; short dmDuplex; short dmYResolution; short dmTTOption; short dmCollate; BCHAR dmFormName[CCHFORMNAME]; WORD dmLogPixels; DWORD dmBitsPerPel; DWORD dmPelsWidth; DWORD dmPelsHeight; union { DWORD dmDisplayFlags; DWORD dmNup; } DWORD dmDisplayFrequency; #if(WINVER >= 0x0400) DWORD dmICMMethod; DWORD dmICMIntent; DWORD dmMediaType; DWORD dmDitherType; DWORD dmReserved1; DWORD dmReserved2; #if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400) DWORD dmPanningWidth; DWORD dmPanningHeight; #endif #endif /* WINVER >= 0x0400 */ } DEVMODE;" self defineField: #dmDeviceName type: (ArrayField type: String length: 32); defineField: #dmSpecVersion type: WORDField filler; defineField: #dmDriverVersion type: WORDField filler; defineField: #dmSize type: WORDField writeOnly beOverride; defineField: #dmDriverExtra type: WORDField filler; defineField: #dmFields type: DWORDField filler; defineField: #dmOrientation type: WORDField new offset: 44; defineField: #dmPaperSize type: WORDField new offset: 46; defineField: #dmPaperLength type: WORDField filler offset: 48; defineField: #dmPaperWidth type: WORDField filler offset: 50; defineField: #dmPosition type: (StructureField type: POINTL) beFiller offset: 44; defineField: #dmScale type: WORDField filler; defineField: #dmCopies type: WORDField filler; defineField: #dmDefaultSource type: WORDField filler; defineField: #dmPrintQuality type: WORDField filler; defineField: #dmColor type: WORDField filler; defineField: #dmDuplex type: WORDField filler; defineField: #dmYResolution type: WORDField filler; defineField: #dmTTOption type: WORDField filler; defineField: #dmCollate type: WORDField filler; defineField: #dmFormName type: (ArrayField type: String length: 32) beFiller; defineField: #dmLogPixels type: WORDField filler; defineField: #dmBitsPerPel type: DWORDField filler; defineField: #dmPelsWidth type: DWORDField filler; defineField: #dmPelsHeight type: DWORDField filler; defineField: #dmDisplayFlags type: DWORDField filler offset: 116; defineField: #dmNup type: DWORDField filler offset: 116; defineField: #dmDisplayFrequency type: DWORDField filler; defineField: #dmICMMethod type: DWORDField filler; defineField: #dmICMIntent type: DWORDField filler; defineField: #dmMediaType type: DWORDField filler; defineField: #dmDitherType type: DWORDField filler; defineField: #dmReserved1 type: DWORDField filler; defineField: #dmReserved2 type: DWORDField filler; defineField: #dmPanningWidth type: DWORDField filler; defineField: #dmPanningHeight type: DWORDField filler! ! !DEVMODE class categoriesFor: #defineFields!initializing!public! ! "Filed out from Dolphin Smalltalk XP"! Win32Structure subclass: #DEVNAMES instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: ''! DEVNAMES guid: (GUID fromString: '{776A9E91-190A-4EA6-969C-92BC7B280AD9}')! DEVNAMES comment: 'See [DolphinImageFolder]/Ian Bartholomew/Documentation for details (C) 2004 Ian Bartholomew [hidden email] Public Domain Freeware'! !DEVNAMES categoriesForClass!External-Data-Structured-Win32!IDB Goodies! ! !DEVNAMES class methodsFor! defineFields "Define the fields of the Win32 DEVNAMES structure. DEVNAMES compileDefinition DEVNAMES decompileDefinition typedef struct _deviNAMES WORD wDriverOffset; WORD wDeviceOffset; WORD wOutputOffset; WORD wDefault; // strings follow here } DEVNAMES" self defineField: #wDriverOffset type: WORDField new; defineField: #wDeviceOffset type: WORDField new; defineField: #wOutputOffset type: WORDField new; defineField: #wDefault type: WORDField new! ! !DEVNAMES class categoriesFor: #defineFields!initializing!public! ! "Filed out from Dolphin Smalltalk XP"! Win32Structure subclass: #PRINTPAGERANGE instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: ''! PRINTPAGERANGE guid: (GUID fromString: '{2CA95384-EE76-4CE7-A2E8-D8BF613E90F8}')! PRINTPAGERANGE comment: 'See [DolphinImageFolder]/Ian Bartholomew/Documentation for details (C) 2004 Ian Bartholomew [hidden email] Public Domain Freeware'! !PRINTPAGERANGE categoriesForClass!External-Data-Structured-Win32!IDB Goodies! ! !PRINTPAGERANGE class methodsFor! defineFields "Define the fields of the Win32 PRINTPAGERANGE structure. PRINTPAGERANGE compileDefinition typedef struct tagPRINTPAGERANGE { DWORD nFromPage; DWORD nToPage; } PRINTPAGERANGE;" self defineField: #nFromPage type: DWORDField new; defineField: #nToPage type: DWORDField new! ! !PRINTPAGERANGE class categoriesFor: #defineFields!initializing!public! ! "Filed out from Dolphin Smalltalk XP"! Win32Structure subclass: #PRINTDLGEX instanceVariableNames: 'pageRanges' classVariableNames: '' poolDictionaries: '' classInstanceVariableNames: ''! PRINTDLGEX guid: (GUID fromString: '{B691F392-B721-4F29-BB6D-3F2477CC294A}')! PRINTDLGEX comment: 'See [DolphinImageFolder]/Ian Bartholomew/Documentation for details (C) 2004 Ian Bartholomew [hidden email] Public Domain Freeware'! !PRINTDLGEX categoriesForClass!External-Data-Structured-Win32!IDB Goodies! ! !PRINTDLGEX methodsFor! dwSize: anObject bytes dwordAtOffset: 0 put: anObject! initialize super initialize. self lpPageRanges: (pageRanges := StructureArray length: 10 elementClass: PRINTPAGERANGE); nMaxPageRanges: 10! ownerView: aView "Set the parent window for the dialog to aView." | hWnd | hWnd := aView asParameter. hWnd isNull ifFalse: [self hwndOwner: hWnd]! pageRangeAt: anInteger ^pageRanges at: anInteger! ! !PRINTDLGEX categoriesFor: #dwSize:!accessing!public! ! !PRINTDLGEX categoriesFor: #initialize!initializing!public! ! !PRINTDLGEX categoriesFor: #ownerView:!accessing!public! ! !PRINTDLGEX categoriesFor: #pageRangeAt:!accessing!public! ! !PRINTDLGEX class methodsFor! defineFields "Define the fields of the Win32 PRINTDLG structure. PRINTDLGEX compileDefinition PRINTDLGEX decompileDefinition typedef struct tagPDEX { DWORD lStructSize; HWND hwndOwner; HGLOBAL hDevMode; HGLOBAL hDevNames; HDC hDC; DWORD Flags; DWORD Flags2; DWORD ExclusionFlags; DWORD nPageRanges; DWORD nMaxPageRanges; LPPRINTPAGERANGE lpPageRanges; DWORD nMinPage; DWORD nMaxPage; DWORD nCopies; HINSTANCE hInstance; LPCTSTR lpPrintTemplateName; LPUNKNOWN lpCallback; DWORD nPropertyPages; HPROPSHEETPAGE *lphPropertyPages; DWORD nStartPage; DWORD dwResultAction; } PRINTDLGEX, LPPRINTDLGEX;" self defineField: #dwSize type: DWORDField writeOnly beOverride; defineField: #hwndOwner type: DWORDField new; defineField: #hDevMode type: HANDLEField new; defineField: #hDevNames type: HANDLEField new; defineField: #hDC type: DWORDField new; defineField: #flags type: DWORDField new; defineField: #flags2 type: DWORDField filler; defineField: #exclusionFlags type: DWORDField filler; defineField: #nPageRanges type: DWORDField new; defineField: #nMaxPageRanges type: DWORDField new; defineField: #lpPageRanges type: (StructureArrayPointerField type: PRINTPAGERANGE length: 10); defineField: #nMinPage type: DWORDField new; defineField: #nMaxPage type: DWORDField new; defineField: #nCopies type: DWORDField new; defineField: #hInstance type: DWORDField filler; defineField: #lpPrintTemplateName type: DWORDField filler; defineField: #lpCallback type: DWORDField filler; defineField: #nPropertyPages type: DWORDField filler; defineField: #lphPropertyPages type: DWORDField filler; defineField: #nStartPage type: DWORDField new; defineField: #dwResultAction type: DWORDField new! ! !PRINTDLGEX class categoriesFor: #defineFields!initializing!public! ! "Filed out from Dolphin Smalltalk XP"! !ComDlgLibrary methodsFor! printDlgEx: aWinPRINTDLGEX "Displays a Print dialog box or a Print Setup dialog box. The Print dialog box enables the user to specify the properties of a particular print job. HRESULT PrintDlgEx( LPPRINTDLGEX lppd // address of structure with initialization data );" <stdcall: hresult PrintDlgExA PRINTDLGEX*> #idbAdded. ^self invalidCall! ! !ComDlgLibrary categoriesFor: #printDlgEx:!idb goodies!primitives!public!win32 functions-common dialog box! ! =~=~=~=~=~= -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
In reply to this post by Peter Simmonds
Peter Simmonds wrote:
> How can I > programmatically change the orientation of the paper. That is from > Portrait to Landscape and vice versa. That's one of the bits of the Windows printing API that isn't exposed in the standard Dolphin image. As a starting point, I suggest that you get hold of Ian's 'IDB Printer' package, and then see the methods Printer>>beLandscape and #bePortrait. <http://www.idb.me.uk/goodies5/goodies5.html> Ian, are you open to a suggestion ? I'd like to use the low-level stuff from that package, but the higher level 'Printer' abstraction doesn't really fit with /my/ printer framework ;-) Would you be willing to split the Window API bit out into a separate package ? Please don't bother if it's a fuss, of course. -- chris |
In reply to this post by Chris Uppal-3
Chris,
[snip] > to help with that, although it is, as the comment states, just a kludge. You > will need a similar hack (or something better) in order to get the fonts scaled > correctly. FWIW, a kludge might be just what is required. > Windows also has lots of bells and whistles for manipulating the mapping > between coordinates and actual Pixels, all of which confuse me utterly. Good, that means I'm not alone :) > They > are not activated by default, so the mapping is 1-to-1 unless you change it > yourself. (I believe that you should be able to get better results if you /do/ > use the advanced mappings, but I've never had the courage to try ;-) I tried the mapping modes/viewport/origin stuff, and wasn't very happy with it. IIRC, there are some newer transformations, but I've ended up with a home-grown solution that works. > Be prepared to waste a lot of ink ;-) I found it helpful to install a > PostScript printer driver, set to print to file, and then used the Aladdin > PostScript viewer (freeware) to look at the results -- it's not perfect but it > has probably saved me at least one printer cartridge already. For the things that I print, much of the work is done by common rendering objects that generate on-screen as well as printer graphics. All coordinates are specified in inches (thanks to Smalltalk, they can be a mix of floats or integers as appropriate), and the rendering scales/truncates to the target pixels. Much of the "wasted ink" can be avoided by sending graphics to bitmaps and viewing them in an ImagePresenter. Of course, there are printer-specific problems (pagination, margins, etc.) that lend themselves to Blair's suggestion. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Ian Bartholomew-19
Peter,
> With great difficulty, unfortunately. I've extracted some code from my > printer goodie that will work for the _default_ printer (you don't get a > normal PrinterDialog that allows you to choose) as an example. FileIn the > code between the =~=~=s, it adds some required structures and an interface > method, then evaluate the following in a workspace. Changing the argument > in the second section allows you to print in Portrait(1) or Landscape(2) Intending no disrespect to Ian's hard work, I find myself wondering whether it is necessary. If you control the content of the printed page, then you should be able to simply rotate everything by 90 degrees, either using a matrix transformation, or by a more brute force approach. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Chris Uppal-3
Chris,
> Ian, are you open to a suggestion ? Always! > I'd like to use the low-level > stuff from that package, but the higher level 'Printer' abstraction > doesn't really fit with /my/ printer framework ;-) Would you be > willing to split the Window API bit out into a separate package ? I'm not sure you would gain much. Each Printer instance maintains PRINTDLGEX and PAGESETUPDLG structures that hold the required state of the printer - mainly in it's DEVMODE attribute. All the rest of the functions, including the low level stuff, use these structures, as do the PrintSetupDialog and PageSetupDialog dialogs. The low level stuff mainly works by tweaking bits in the DEVMODE structure, as you saw in my earlier orientation example, so there wouldn't really be a lot of code to add to any api package and you would still need a lot of non-api support code in the main package. Roughly how does your printer framework work? -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
In reply to this post by Schwab,Wilhelm K
Bill,
> Intending no disrespect to Ian's hard work, I find myself wondering > whether it is necessary. If you control the content of the printed > page, then you should be able to simply rotate everything by 90 > degrees, either using a matrix transformation, or by a more brute > force approach. That would work but using the normal procedure, even though it is more difficult, is going to be more flexible and also presents a standard way of working to the user. By that I mean that things like varying the margins, changing printers and all the other settings that the PrintSetup and PageSetup dialogs allow will be accessible in the "normal" Windows way. It may well be that Peter's application doesn't need any of this and just rotating the bitmaps may well be the easiest solution. -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
In reply to this post by Ian Bartholomew-19
Ian,
> Roughly how does your printer framework work? Hmm, you don't believe in asking /easy/ questions do you ;-) I haven't really had a "vision" for how it works -- it's sedimenting out from a collection of ad hoc printing code and is still two iterations short of an abstraction. The best I can put it is that it treats printing as a process. There is no real concept of printing something "on" a printer -- it's too page-oriented for that. The key abstraction is (or will be) a PrintController, which may be a PrintPreview function (window) or a PrintDialog+PrintProgress function (sequence of windows). The application creates a PrintController, gives it some initial settings, and then largely forgets about printing. The PrintController calls back into the application when it wants a page of graphics by sending #printPage:on:in: with a page number, a Canvas (possibly a PrintCanvas possibly a normal screen Canvas), and a target Rectangle. The PrintController looks after things like selecting the page to view in PP, or collation and page-range selection in real printing (which is important to me). I'm thinking about adding something whose role in printing is similar to a View in MVP -- something with the job of rendering a page of a Model on a Canvas. Or maybe just rendering a page on a Canvas without requiring an explicit Model. Anyway, at the moment it has reached the point where I'd like to be able to pass some sort of PrintSettings object around -- particularly so that the PP function and real printing could agree on whether to use Landscape mode without the user having to tell /both/ of them. Also it'd be nice to use the improved print dialog in XP (one of XP's few genuine improvements, IMO). It's a personal thing, but I'd be more comfortable managing the dialogs in the same way as a PrintDialog in vanilla Dolphin (I already have my own PrintDialog subclass that exposes the important -- to me -- "advanced" options in a PRINTDLG). I /could/ create my own wrappers for all the relevant Windows structures, but you've already done it -- what's more, I use your IDE printing extensions so they are already present in my image ! So I'd rather re-use your work, but I'd without your abstraction (which would overlap confusingly with mine). I'm greedy, I know ;-) -- chris P.S. Now I've written all this, I have a /much/ clearer picture of what the next iteration will look like. Ain't upfront design wonderful... |
In reply to this post by Ian Bartholomew-19
"Ian Bartholomew" <[hidden email]> wrote in message
news:9Nqsc.6847$[hidden email]... > Chris, > > > Ian, are you open to a suggestion ? > > Always! Ian, Since you are taking requests... ;) I seem to recall that you have different versions of a package related to printing for Window XP and non-XP (or maybe it is a different SP of XP). I think it is the RTF printing support. I wonder how much effort it might be to support both versions in one package conditionally at runtime? The problem I have is that I am using it in a deployed application to print RTF files. I am using a slightly tweaked older version and have been afraid to upgrade. Perhaps I should just use the lowest common denominator version. Do you think that would still work, or did the SP break something? Will I need to trick your installer into letting me have the older XP package if my XP version is newer? BTW: Thank you for developing your Dolphin goodies. We all appreciate them very much, and you have set a great community precedent for sharing that many of us try to aspire to. Your goodies inspired me to release some of my own. Chris |
In reply to this post by Chris Uppal-3
Chris,
>> Roughly how does your printer framework work? > > Hmm, you don't believe in asking /easy/ questions do you ;-) And there was me thinking I was being kind when I prepended the question with "roughly" > I haven't really had a "vision" for how it works -- it's sedimenting > out from a collection of ad hoc printing code and is still two > iterations short of an abstraction. :-) I've got a lot of code in that state, as you may have noticed. > The best I can put it is that it treats printing as a process. [snip] I _think_ I see what you are aiming for but I admit I can't really see why it would be preferable to the more usual way of printing - creating a "Printer" and then, either directly or indirectly, sending it pages to print. It sounds a bit like you are just trying to duplicate the services provided by the Windows PrintSpooler?. > Anyway, at the moment it has reached the point where I'd like to be > able to pass some sort of PrintSettings object around -- particularly > so that the PP function and real printing could agree on whether to > use Landscape mode without the user having to tell /both/ of them. That's basically what I'm using the PRINTDLGEX structure for. The PrintDialog and PageSetupDialog can both use it and share the required state. I can also access it from, for example, the PrintPreview to generate a valid preview. As you mentioned earlier though, my Printing is mainly used in conjunction with a RichEdit so there may be a better way to do it in a more general Printer class?. > I /could/ create my own wrappers for all the relevant Windows > structures, but you've already done it -- what's more, I use your IDE > printing extensions so they are already present in my image ! So I'd > rather re-use your work, but I'd without your abstraction (which > would overlap confusingly with mine). I'm greedy, I know ;-) OK. I've more or less decided to have another look at the Printer classes (see the other Chris' post) so I'll see if I can redo the packaging to make it easier to use. -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
In reply to this post by Christopher J. Demers
Chris,
> Since you are taking requests... ;) I seem to recall that you have > different versions of a package related to printing for Window XP and > non-XP (or maybe it is a different SP of XP). I think it is the RTF > printing support. I wonder how much effort it might be to support > both versions in one package conditionally at runtime? There are two reasons why the Printing goodies have a number of versions 1) The PrintDialog interface and PRINTDLG/PRINTDLGEX structures are different for early (ME/98) versions of Windows. The newer api support in 2000/XP has a number of enhancements that I wanted to use. 2) The RichEdit support in XP(SP1) differs from XP/2000 which differs from earlier version. Again, I wanted to use the new api if possible. > I wonder how much effort it might be to support > both versions in one package conditionally at runtime? It might well be, I can't really remember exploring that avenue. It may result in some duplication but could be easier than trying to maintain separate source packages . My other problem is that I haven't got anything other than 2000/XP(SP1) to test on so code for the other Windows will contain a bit of guesswork as I will be relying on the printed documentation. > The problem I > have is that I am using it in a deployed application to print RTF > files. I am using a slightly tweaked older version and have been > afraid to upgrade. Perhaps I should just use the lowest common > denominator version. Do you think that would still work, or did the > SP break something? Will I need to trick your installer into letting > me have the older XP package if my XP version is newer? I'll have a look at the whole Printing goodie with a view to redoing the packaging (see the other other Chris' post) and integrating all the different versions into one. <note to me> There's only 2000 sheets of paper and 3 bottles of printer ink left in the storage cupboard so I'd better stock up soon if I'm going to start playing with the Printing api again..... > BTW: Thank you for developing your Dolphin goodies. Thanks for the kind comments. -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
In reply to this post by Ian Bartholomew-19
Ian,
> I _think_ I see what you are aiming for but I admit I can't really see why > it would be preferable to the more usual way of printing - creating a > "Printer" and then, either directly or indirectly, sending it pages to > print. It sounds a bit like you are just trying to duplicate the services > provided by the Windows PrintSpooler?. I suspect that Chris is trying to "turn objects into printed graphics", which does have a lot of overhead that can be abstracted. Windows (usually) does a fine job of spooling graphics to a printer, but it does not provide much (and probably should not try) for breaking things up across pages, etc. Windows can translate and clip; it also scales, though I prefer to do that myself. Regardless of whether one turns to MS for scaling, there is still the question of which transformation, which clipping rectangle, etc. to use for each object on each page. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
In reply to this post by Ian Bartholomew-19
Ian,
> > The best I can put it is that it treats printing as a process. > [snip] > > I _think_ I see what you are aiming for but I admit I can't really see why > it would be preferable to the more usual way of printing - creating a > "Printer" and then, either directly or indirectly, sending it pages to > print. It sounds a bit like you are just trying to duplicate the services > provided by the Windows PrintSpooler?. Hmm, why /did/ I do it that way... ? Well, the immediate, practical, reason is that my print previewer has a tabbed UI with one tab for each page, and generates the graphics for the selected page on demand (its not a tabbed container, just a "tab" view of a list (1 to: n) plus a single graphics pane for previewing the "current" page). Obviously the user will ask to see pages in whatever order suits, so it's easier to make the "architecture" be driven by the consumer of pages rather than the supplier. Also I want page ranges, collation, multiple-printing to work (the later two are implemented badly or not at all in the print drivers I've encountered), so I code that myself[*]. The code's simple enough but I don't want to duplicate the logic in every page provider. So I've pulled it out into the page consumer (in this case the "print progress" dialog), where it sits very nicely with the consumer-driven way the previewer works. ([*] Not that the copies and collation flags actually work in Windows; it seems to be a long standing bug (even affects IE6) that I don't yet have a workaround for :-( Someday...) But that's the practical reason. The /real/ reason is that I have never been thinking in terms of a document as a single entity that is flowed over a number of pages. I've always been thinking in terms of a collection of largely independent pages. So the "inside-out" architecture seems quite natural, even though it's a bit more work. Not all applications are like that, it's just how my particular set of applications turned out. Though I do have a vague feeling that the page-centric picture is more general than flowed-document -- there is always going to be a tendency for page-centric thinking to sneak in by the back door even in flowed-document (page numbering, widow control, and the like). > > Anyway, at the moment it has reached the point where I'd like to be > > able to pass some sort of PrintSettings object around -- particularly > > so that the PP function and real printing could agree on whether to > > use Landscape mode without the user having to tell /both/ of them. > > That's basically what I'm using the PRINTDLGEX structure for. The > PrintDialog and PageSetupDialog can both use it and share the required > state. I can also access it from, for example, the PrintPreview to > generate a valid preview. > > As you mentioned earlier though, my Printing is mainly used in conjunction > with a RichEdit so there may be a better way to do it in a more general > Printer class?. I'm currently trying to create a PrintSettings object that can be passed around. The basic idea seems simple enough -- it's about half of your Printer class, so I can copy large chunks of that (BTW, /especial/ thanks for that -- never in a thousand years would I have worked out how to get at the DEVMODE thingies, for instance. Deep magic!). Unfortunately, it's proving tricky in the details -- the problem is that I want narrow control over the print dialog, so I want that to be an externally "visible" object, but the dialog (CUPrintDialog) has to share the PRINTDLG[EX] with the PrintSettings. I think something similar will happen with the page setup too, but I haven't really thought about that yet. I suspect that I'll end up with something a bit like the Holy Trinity -- three objects that are yet one (though, this being printing code, and /Windows/ printing code at that, the word "Holy" is totally inappropriate ;-) More prosaically, I think the PrintSettings will "own" a CUPrintDialog and a CUPageSetupDialog, but be willing to let external code "see" the dialogs and control when they are shown. > OK. I've more or less decided to have another look at the Printer classes > (see the other Chris' post) so I'll see if I can redo the packaging to > make it easier to use. Many thanks ! -- chris |
In reply to this post by Christopher J. Demers
Chris,
> Since you are taking requests... ;) I seem to recall that you have > different versions of a package related to printing for Window XP and > non-XP (or maybe it is a different SP of XP). I've had a go at refactoring the printer goodie and have come up with a set of packages that I _think_ will work on all Windows OSs (all I know is that it works on XP(SP1) and 2000 which are the only ones I have). I've gone back to just using the PrintDlg api (rather than trying to use PrintDlg and PrintDlgEx), which means I lose a small bit of functionality, but makes it a lot easier to accommodate all OSs. I've also factored out all the places where the RichEdit class (my wrapper for the RichTextEdit control available in XP(SP1)) is used so that doesn't cause a problem any more. There is a download (18K) available at the following address if you, or anyone else, would like to try it but please bear in mind that is just a test version so all the obvious warnings and disclaimers apply. http://www.idb.me.uk/files/printing.zip Unzipping the downloaded file should give you a single folder called Printer which contains 6 packages. The folder must be moved to my usual goodies directory tree - normally creating a "My Documents/Dolphin Smalltalk 5.1/Ian Bartholomew/Printer" folder. You can't install these packages into an image that already contains any of my existing printer support so I would recommend using a clean Dolphin 5.1.4 image. Installing the package "IDB IDE Printer Extensions" should drag in all the others as prerequisites. Once installed all the Dolphin browsers should have "Print/Print Preview/Page Setup" options added to the File menu. You can also use it programmatically - "create a Printer for the default system printer" p := Printer new. "Change the target printer or it's properties" p showPrintDialog. "Print to it - works with RichTextView instances as well" p print: 'hello world' I _really_ would appreciate any feedback on this, good or bad, especially from anyone using it on 98 or ME. -- Ian Use the Reply-To address to contact me. Mail sent to the From address is ignored. |
Free forum by Nabble | Edit this page |