Does anyone know if its possible to have a TextPresenter with a
background image? I tried putting an ImageViewer behind it with the TextPresenter set to transparant with no joy. I'm guessing I may need to subclass the TextPresenter and override some paint method? Basically I want to set a faded watermark behind a multiline text entry field. ( and maybe also the same on a ListPresenter ). Mark |
"Mark Derricutt" <[hidden email]> wrote in message
news:cinubh$[hidden email]... > Does anyone know if its possible to have a TextPresenter with a background > image? > > I tried putting an ImageViewer behind it with the TextPresenter set to > transparant with no joy. > The standard Windows controls, with a few exceptions, do not really support transparency.... > I'm guessing I may need to subclass the TextPresenter and override some > paint method? \ ... however you may be able to achieve what you want by using a bitmap brush for the background. Currently you can only specify a solid colour background brush for controls (by setting the #backcolor aspect) in our standard wrapper classes. We will almost certainly be adding the ability to set an arbitrary background brush in the next version (we want to be able to support gradient fills in particular), but in the meantime you will have to subclass MultilineTextEdit and add the support yourself. >... > Basically I want to set a faded watermark behind a multiline text entry > field. ( and maybe also the same on a ListPresenter ). You need to override #onColorRequired: to answer the handle to a bitmap brush. You will also need to stub-out the ControlView>>onEraseBackground: implementation, which shouldn't really be there at all, so just override it and return nil (although this is not strictly necessary if you ensure that the backcolor is nil). This will cause the text edit control to erase its own background, and it will then use the background brush you supply (from your implementation of #onColorRequired:) to erase its own background, having the effect of painting the background using a bitmap. I did a quick and dirty experiment to try this out. First I created a Bitmap brush in a workspace: bmp := Bitmap fromFile: 'c:\windows\gone fishing.bmp'. B := Brush bitmap: bmp. Then I defined #onColorRequired: in MultlineTextEdit as follows (obviously don't save your image after this, or delete the method first): onColorRequired: aColorEvent super onColorRequired: aColorEvent. (aColorEvent canvas) brush: B; setBkMode: TRANSPARENT. ^B asParameter Now try it out: MultilineTextEdit show Try commenting out the #setBkMode: message to see what effect that has. Anyway you will see that it basically works, although as an apparent result of setting the background mode of the canvas to transparent it doesn't erase on backspace (or select/deselect) so that needs some thought and further work to see if it can be worked around. Regards Blair |
Blair McGlashan wrote:
Hi Blair, finally getting around to looking at this.... >I did a quick and dirty experiment to try this out. First I created a Bitmap >brush in a workspace: > > I subclassed MultilineTextEdit and created the brush in #initialize and added the #onColorRequired override, seems to be doing something but just gives me a "not indexable" error. 11:24:09 AM, Wednesday, October 06, 2004: 'not indexable' UndefinedObject(Object)>>errorAt: UndefinedObject(Object)>>at: BrushedMultilineTextEdit(View)>>baseStyle BrushedMultilineTextEdit(View)>>parentView: BrushedMultilineTextEdit(View)>>showShell BrushedMultilineTextEdit class(View class)>>show This seems to happen on any bitmap I've tried or created. Mmmm. Initiallly I thought this might be something to do with image formats but even if I try set the brush to "brush := Brush gray" I get the 'not indexable' problem. Did this work for you when you tried it in your quick test? Hopefully I'll have some more time this afternoon to look at this closer... mark |
[ From your previous posts, it sounds like you're still pretty new to
Smalltalk, so I'm throwing in some extra information that may or may not be new or useful. ] Mark Derricutt wrote: > I subclassed MultilineTextEdit and created the brush in #initialize and > added the #onColorRequired override, seems to be doing something but > just gives me a "not indexable" error. > First, note this: > 11:24:09 AM, Wednesday, October 06, 2004: 'not indexable' > UndefinedObject(Object)>>errorAt: > UndefinedObject(Object)>>at: ^^^^^^^^^^^^^^^ > BrushedMultilineTextEdit(View)>>baseStyle > BrushedMultilineTextEdit(View)>>parentView: > BrushedMultilineTextEdit(View)>>showShell > BrushedMultilineTextEdit class(View class)>>show > I still forget to look at the object that's reporting the error a lot. When the object is "UndefinedObject", that means that something you're working with is nil. Normally, you get a "message not understood" because you've sent a message that nil doesn't understand, but at: works differently; hence, the "not indexable" error. Anyway, View>>baseStyle just sends a message to creationStyle, which is an instance variable. Looking at uses of it, it should be set in View>>initialize. Either the call to "self defaultStyle" there is returning nil (I didn't look further to see if that was possible), or (more likely, if it was me doing the work) your BrushedMultilineTextEdit>>initialize method doesn't call super initialize. If the second one isn't the problem, I've hopefully left you a couple of other bread crumbs to follow. Randy -- Randy Coulman NOTE: Reply-to: address is spam-guarded. Reassemble the following to reply directly: rcoulman at charter dot net |
Randy Coulman wrote:
> [ From your previous posts, it sounds like you're still pretty new to > Smalltalk, so I'm throwing in some extra information that may or may > not be new or useful. ] Yep - have been reading alot about Smalltalk over the past year or so but actually really been using it for the past month or two. I'm enjoying it - but also finding bits and pieces hellishly fustrating. Although that mostly seems to be a) COM b) MVP c) Windows in general ;p > I still forget to look at the object that's reporting the error a lot. > When the object is "UndefinedObject", that means that something you're > working with is nil. Normally, you get a "message not understood" Doh - as you say, I did forget to look at WHAT was thrown the error... *sigh* > your BrushedMultilineTextEdit>>initialize method doesn't call super > initialize. And there we have it.... added the call to super and voila - perfection ;-) |
Mark Derricutt wrote:
> And there we have it.... added the call to super and voila - > perfection ;-) -almost- have it. The class works fine when doing "BrushedMultilineTextEdit show" in a transcript, but after opening my view and mutating the existing MultilineTextEdit to the new one I see my bitmap in the view composer ( yay ) but when I a) test the view b) save it and run it in my app I just see the normal MultilineTextEdit. Mmmmm. |
Mark Derricutt wrote:
> -almost- have it. The class works fine when doing > "BrushedMultilineTextEdit show" in a transcript, but after opening my > view and mutating the existing MultilineTextEdit to the new one I see > my bitmap in the view composer ( yay ) but when I a) test the view b) > save it and run it in my app I just see the normal Ok, just replying to myself once more for googlesake, the Mutated version -is- working, as I can add "self halt" to #onColourRequired and see it trip up all the time. However, what -isn't- being run is #initialize. Hmmmmmm. Time to go hunting. |
Mark Derricutt wrote:
> Ok, just replying to myself once more for googlesake, the Mutated > version -is- working, as I can add "self halt" to #onColourRequired > and see it trip up all the time. However, what -isn't- being run is > #initialize. Score. Switching from loading my BMP in #initialize to loading it in #onViewOpened and she's away laughing ;-) Mark |
Mark,
> Score. Switching from loading my BMP in #initialize to loading it in > #onViewOpened and she's away laughing ;-) One more thing to check: does it work if the view/presenter is open when you save the image and then restart Dolphin? IIRC, #onViewOpened is not called in that scenario. Sorry if I am sending you in pursuit of a wild aquatic fowl. Have a good one, Bill -- Wilhelm K. Schwab, Ph.D. [hidden email] |
Bill Schwab wrote:
> One more thing to check: does it work if the view/presenter is open > when you save the image and then restart Dolphin? IIRC, #onViewOpened > is not called in that scenario. Sorry if I am sending you in pursuit > of a wild aquatic fowl. > > Have a good one, > Not sure - just running off for a bus home so will have to check once I get to the other end of the city :). |
In reply to this post by talios@gmail.com
"Mark Derricutt" <[hidden email]> wrote in message
news:cjvrq4$[hidden email]... > Mark Derricutt wrote: > >> Ok, just replying to myself once more for googlesake, the Mutated >> version -is- working, as I can add "self halt" to #onColourRequired and >> see it trip up all the time. However, what -isn't- being run is >> #initialize. > > Score. Switching from loading my BMP in #initialize to loading it in > #onViewOpened and she's away laughing ;-) Yes, #initialize is only run the first time a View instance is created. Subsequently to that one is effectively deserialising a pre-initialised instance. Depending on how you've created your Bitmap, however, you might not need to recreate it since it may, if loaded from a resource or file, be able to recreate itself on demand. Try this example in a workspace. bmp := Bitmap fromFile: 'c:\windows\Gone fishing.bmp'. bmp "Ctrl+I - inspect the bitmap and verify the image has loaded. Close the inspector." ... Now save the image, exit and restart" bmp basicHandle "Ctrl+D - this will be nil on restart" bmp "Ctrl+I - inspect the bitmpa, and verify that the image has reloaded." bmp basicHandle "Ctrl+D - this will now be non-nil" If your bitmap is created by drawing onto a Bitmap canvas, then it is not persistent, and will not be valid on restarting an image. For example if you snapshot the desktop like this: bmp := Bitmap displayCompatibleWithExtent: View desktop extent. bmp canvas bitBlt: View desktop canvas rectangle: View desktop rectangle to: 0@0 rop: 13369376 "SRCCOPY". Then on restart the bitmap will be blank because not attempt is currently made to persist the bits of a bitmap in the image file. Regards Blair |
In reply to this post by Blair McGlashan-3
Blair McGlashan wrote:
>Anyway you will see that it basically works, although as an apparent result >of setting the background mode of the canvas to transparent it doesn't erase >on backspace (or select/deselect) so that needs some thought and further >work to see if it can be worked around. > > Blair - I have a work around for this, when responding to #keyPressed: I now have the following: BrushedMultilineEdit>>processKeyPress: aKeyEvent aKeyEvent wParam = 8 ifTrue: [self view refreshContents]. However, this causes the whole view to flicker and redraw in a somewhat nasty fashion. I notice if I changed this to "contentPresenter view refreshContents" nothing happened; no error but no refresh either. I didn't seem to see any refresh methods on the Presenter itself ( or its ancesters but I might be blind here ). It's currently better than NOT having the refresh and having text draw over itself, but I'm sure the flicker will drive me insane ;p Any ideas? Mark |
Mark Derricutt wrote:
> It's currently better than NOT having the refresh and having text draw > over itself, but I'm sure the flicker will drive me insane ;p Any ideas? You might be able to do something clever by either providing your own paint procedure and/or using the restricted form of #invalidate:, but I wanted to suggest something simpler. Would it be adequate if you just removed the background[*] while the control has focus (i.e put a <self hasFocus> test into the #onColorRequired code), and do <self invalidate> in #onKillFocus, so that the background is restored when the user moves away from the control ? I'd set a normal" background colour that was roughly similar to the bitmap's average to minimise the visual impact of the change. You could even claim that it was done that way to make editing easier ;-) -- chris |
Chris Uppal wrote:
>You might be able to do something clever by either providing your own paint >procedure and/or using the restricted form of #invalidate:, but I wanted to >suggest something simpler. Would it be adequate if you just removed the > > I remember from my old delphi does making use of the LockWindowsUpdate() method to refuse updating of the display untill you'd done everything but that was only really usefull when removing say 1000+ items from a listview/listbox etc. etc. So probably wouldn't really be appropriate here. >background[*] while the control has focus (i.e put a <self hasFocus> test into >the #onColorRequired code), and do <self invalidate> in #onKillFocus, so that >the background is restored when the user moves away from the control ? I'd set > > >You could even claim that it was done that way to make editing easier ;-) > > It's possible. The whole reason for putting an image behind the text area is for product branding. Originally my bosses wanted a solid hunky image plonked on the dialog which looked somewhat yucky, and out of place, so I thought of having this faded/watermark faintly behind the edit area which would provide branding space, and not be obtrusive. You're idea does have good merit thou, I could leave the image there untill they start typing there message and remove it then. mmmm. I'll have to toy with that in the morning when I get back to the office. mark |
In reply to this post by talios@gmail.com
"Mark Derricutt" <[hidden email]> wrote in message
news:ck2akg$[hidden email]... > Blair McGlashan wrote: > >>Anyway you will see that it basically works, although as an apparent >>result of setting the background mode of the canvas to transparent it >>doesn't erase on backspace (or select/deselect) so that needs some thought >>and further work to see if it can be worked around. >> > Blair - I have a work around for this, when responding to #keyPressed: I > now have the following: > > BrushedMultilineEdit>>processKeyPress: aKeyEvent > aKeyEvent wParam = 8 ifTrue: [self view refreshContents]. > > However, this causes the whole view to flicker and redraw in a somewhat > nasty fashion. Yes I can imagine. > > I notice if I changed this to "contentPresenter view refreshContents" > nothing happened; no error but no refresh either. I didn't seem to see > any refresh methods on the Presenter itself ( or its ancesters but I might > be blind here ). Well without knowing what contentPresenter is, it is difficult to guess at why ... :-) > > It's currently better than NOT having the refresh and having text draw > over itself, but I'm sure the flicker will drive me insane ;p Any ideas? I'll have a think, but as a start point you could try invalidating only the area occupied by the text. This isn't perhaps as hard as it sounds because the #calculateExtent method will give you back the correct height for the text (plus a blank line) in the control at its current width: m := MultilineTextEdit show. m text: 'Blah de blah blah blah, de blah blah blah, blahdeblah'. "Now run this next line separately" m canvas fillRectangle: m clientRectangle brush: Brush black. "When you evaluate this next line, you should see that only the text and a blank line gets restored" m invalidateRect: (0@0 extent: m calculateExtent). This might help until someone can think of a better way - its probably worth trawling VB (or general Windows) programming tip sites, since the same issue would apply to anyone attempting to use a textured (bitmap) brush as the background of a multiline edit control. Regards Blair |
Blair McGlashan wrote:
> "When you evaluate this next line, you should see that only the text and >a blank line gets restored" > m invalidateRect: (0@0 extent: m calculateExtent). > > Excellent - that works a treat, more so than the refresh at least, still a bit of flicker. I was thinking of invalidate as I'd used that years ago in delphi when doing similar things, sadly years of java/linux have hidden win32 api foo deep in the recesses of the mind.... they're slowly starting to resurface - but I'm not sure if I really want them too :P |
Mark Derricutt wrote:
> > m invalidateRect: (0@0 extent: m calculateExtent). > > > > > Excellent - that works a treat, more so than the refresh at least, still > a bit of flicker. Just a thought, but using self invalidateRect: (...) erase: false might reduce the flicker further -- if it works at all... -- chris |
In reply to this post by talios@gmail.com
"Mark Derricutt" <[hidden email]> wrote in message
news:ck4bh0$[hidden email]... > Blair McGlashan wrote: > >> "When you evaluate this next line, you should see that only the text >> and a blank line gets restored" >> m invalidateRect: (0@0 extent: m calculateExtent). >> > Excellent - that works a treat, more so than the refresh at least, still a > bit of flicker. I was thinking of invalidate as I'd used that years ago > in delphi when doing similar things, sadly years of java/linux have hidden > win32 api foo deep in the recesses of the mind.... they're slowly > starting to resurface - but I'm not sure if I really want them too :P Hmmm, getting the EDIT control to work correctly with any background other than a solid colour is really quite a tricky problem. Superficially it is easy to get it to paint on a textured background, but there are a lot of redisplay issues when editing, and also scrolling. I had a couple of goes at it over the last couple of days, and found a couple of helpful ideas on "advanced VB" sites, although the implementations were a bit of a mess (just as much a the fault of VB as the programmers that created them mind you). Anyway I have finally come up with a solution that paints correctly and does not exhibit flicker. Scrolling is a bit slower than normal, but usable. Anyway I hope it satisfies your requirement, and that it is of general utility. The package can be downloaded from: http://object-arts.com/Lib/Update/Dolphin/5.1/MTEWithImage.zip Please let me know what you think. Regards Blair |
Free forum by Nabble | Edit this page |