[2008] Get part of background image covered by ListView control
In my project, I have a form with a background pic that I like, but unfortunately, I also have a ListView on that form which covers most of the picture. Now, is there a way to find the part of the background image concealed by the ListView, and then display it as a background image of the ListView at decreased opacity? You know, like a vague image.
Just one more thing, setting the form's transparency key to the background color of the ListView is not an option.
Can anyone help me? Any help would be greatly appreciated. (and well-rated, too )
Last edited by obi1kenobi; Mar 10th, 2008 at 12:42 PM.
Re: [2008] Get part of background image covered by ListView control
You can override the background draw of the listview control. Just make a new class, inherit the ListView control, add the following function into it:
Code:
Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
'Do nothing (because we want to be transparent).
If DesignMode Then MyBase.OnPaintBackground(pevent)
End Sub
Re: [2008] Get part of background image covered by ListView control
What's DesignMode?
I'm not completely sure how to inherit the ListView. Should I simply write Inherits ListView in the class? And should I inherit the class or the instance?
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
Make a new class... call it "MyListview" or something.
At the top just under the Public Class part, put: Inherits ListView
Now, drop in the line of code above. The line about "DesignMode" is just so that it won't look funny sitting on your form in the designer. You may not even need it.
Re: [2008] Get part of background image covered by ListView control
Originally Posted by Jenner
Make a new class... call it "MyListview" or something.
At the top just under the Public Class part, put: Inherits ListView
Now, drop in the line of code above. The line about "DesignMode" is just so that it won't look funny sitting on your form in the designer. You may not even need it.
Just one more question. Will this make the background completely transparent or will it display a dimmed view of the background like I asked? 'Cos I won't have enough time to change it back if it doesn't work out.
I'm sorry, I must be boring you
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
No, it'll make it completely transparent I'm afraid. I'm sorry, I missed the part about decreased opacity. Ouch, you really do have a problem then. Might be best to "fudge it". i.e. make a copy of the picture, crop it to the visible area, edit it in PhotoShop and post it as a background image of the listbox.
Even if you were to do it, it would be a resource hog. I have a C# routine though that'll take an image and quickly apply a 50% shade to it using an unsafe class.
Re: [2008] Get part of background image covered by ListView control
Yes, I've thought of editing the background in an outside editor, but the problem is, most of the time, the background is tiled, so the tiles must match the form background perfectly, or the effect is lost.
How about this: is there a way to cancel out the pixels in two pictures and then store the output? By 'cancel out', I mean compare pixels and if they are the same, then delete one of them. That would create an "overlay" of some sort, which can then be shaded or something to produce the desired effect. It sounds wild, even to me, but it just might work
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
it would honestly be a royal pain in the butt to do this because the listview doesn't directly support owner drawing. It does support owner drawing for items, subitems, and column headers, but not the control itself.
So you could try a few different methods of cropping the form background image and sticking that in the listview, but you will probably run into road blocks with each method.
Not to mention this will slow down the application, for a feature that is little more than eye candy.
I had done a very similar example for someone using a tab control, but that proved easier because
1) the tabcontrol supports owner drawing of its background
2) unless you specifically set it to do so, it doesn't have scrollbars, so you don't have to deal with scrolling like you do in a listview, which is almost a certainty.
Perhaps you could come up with a tiled background image for the listview that compliements the background image of the form well, instead of it being the same image..
Re: [2008] Get part of background image covered by ListView control
kleinma, am I right in assuming that whatever you've done to the ListView control can also be done to labels? Because I need to do such a thing for labels, make them semi-transparent and stuff, only there won't be any scrolling involved (heh, labels don't scroll ) The only thing I'm worried about is resizing the form.
Would you mind posting what you've written so far, so that I can try and use it for my labels?
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
Labels can be fully transparent, but yeah if you wanted them to be semi transparent, then you would have to use some code to do it.
I don't have the code for a label, but I did do it for a panel, so it should not be a major task to port that code over. I will have a go at it. I am actually just about to publish my article on how I do all this with the source code.
As far as the listview goes though, I gave up on that for now. I had made some progress, but it was ultimately sacrificing performance and making the application too slow.
Re: [2008] Get part of background image covered by ListView control
if you want to post a zipped up project I will have a look at optimizing the code (if its possible)
It looks like you also need a slight offset.. the image doesn't match up exactly.
I have built the "Translucent Button, Panel, TabControl, and Label" so far and I give them offset properties (of datatype point) to offset the image inside. Like i noticed buttons have about a 5 pixel offset due to their border/3d appearance, so I offset the image I apply to them, and it works rather well.
Last edited by kleinma; Apr 2nd, 2008 at 09:26 AM.
Re: [2008] Get part of background image covered by ListView control
Thanks, but I just realised why I never thought of making my apps in WPF, it's so fun and way more structurized (not even mentioning the millions of ways to customize)
But thanks anyways. Other people may like the code
Re: [2008] Get part of background image covered by ListView control
I don't know if I would consider making apps in WPF "fun" considering the development environment is not so matured, it usually makes much longer to do the same, and most people familiar with winforms feel totally lost when it comes to UI design in WPF since it works off of an almost totally different model for UI programming.
Yes it is defenitly way more powerful for building very nice UIs, but I think WPF is still a little ways off from mainstream. The biggest holdback right now is the fact that it only runs on XP SP2 and up, and many people, especially businesses, are still running on older machines with Windows 98 and Windows 2000
Re: [2008] Get part of background image covered by ListView control
Sorry to refresh an old thread, I forgot everything about it. Since there were quite a few people interested in the way to make the ListView transparent, here's how I did it.
Create two forms:
One with the ListView on it, with a transparency key set to Magenta and the ListView's background set to Magenta (a.k.a. Magic Pink).
The other form has no ControlBox, has the same background picture as the first form and has a Panel control with Dock set to Fill, with transparency and color set to some value.
The only thing left to do is bind the two forms together, when the first one is closed/resized/focused, the other one should follow suite. This is the part that I couldn't solve. I posted several threads in the forums, however a solution was not found. The forms would always get separated when the main form lost focus and regained it later and there was no way I could find to fix it. I would always end up with a silly-looking hole in the middle of my application. If anyone can solve this issue, I'd be very grateful, and I'd imagine many other ppl would be too, since a control like this would look very cool.
@Kleinma: If you still have the code you used for the effect in post #10, would you mind showing it to me? I'd love to see how it's done.
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
Originally Posted by Jenner
You can override the background draw of the listview control. Just make a new class, inherit the ListView control, add the following function into it:
Code:
Protected Overrides Sub OnPaintBackground(ByVal pevent As System.Windows.Forms.PaintEventArgs)
'Do nothing (because we want to be transparent).
If DesignMode Then MyBase.OnPaintBackground(pevent)
End Sub
I just got an idea and I need your help. Getting the ListView background completely transparent is a key part of it. So I tried this code, but it has absolutely no effect, the new ListView's background is still white, even when put on a black form.
If you can help me make the background completely transparent, I honestly think I can provide a workaround to make it translucent and performance-friendly at the same time.
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
Ugh... I'm sorry I even posted that solution, because after trying it out completely myself, setting the styles of the listview to owner-draw and such, it just doesn't work. I figured since OnPaint was still happening, just shutting off the OnPaintBackground routine would prevent the control from masking in the background similar to how I do it for transparent panels. It doesn't.
I tinkered with it quite a bit but couldn't get a ListView with even a fully transparent background. Sorry.
Re: [2008] Get part of background image covered by ListView control
It's ok. Thanks for your effort. What I can't understand is why shutting off OnPaint and OnPaintBackground won't make the background transparent, since it shouldn't get painted at all...
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
the listview is a tricky control and its .NET implementation is limited by what the underlying win32 listview control can do...
I had found an article where a guy disected the Win32 API for the listview to be able to insert the translucent image in the bottom corner like windows explorer does, and he got it working, but there were drawbacks, like it only worked well if fullrowselect was false (like windows explorer is) to prevent a highlighted row from covering the image, otherwise painting gets screwed up.
Honestly, there doesn't seem to be any real simple easy way to implement this using the standard listview control...
Re: [2008] Get part of background image covered by ListView control
May I have a look at that article? It may still be good enough.
I have sorted out the translucency effect for any control whose background can be made completely transparent, this is the only issue remaining for the ListView.
I found an article by using Google (unfortunately I lost the link) that stated that the ListView's background may be set to transparent using SendMessage and the LVM_SETBKCOLOR message. MSDN seems to support that:
Originally Posted by MSDN
clrBk - Background color to set or the CLR_NONE value for no background color. List-view controls with background colors redraw themselves significantly faster than those without background colors.
It would be great if we could get this to work.
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
OK I managed to get the ListView's background completely transparent using the method described at the MSDN website, however the Items still have opaque backgrounds. That seems to be the only issue so far. Have a look at what I got:
Do you have any ideas how to solve this one remaining issue?
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
I couldn't find a direct way to track scrolling (e.g. an event which is fired when scrolling) so I decided to track the mouse's movement instead. It's not perfect but it'll have to do if no better solution is found. Please tell me how you made the items' backgrounds transparent if you can.
Here's what I have so far:
Last edited by obi1kenobi; Jan 13th, 2009 at 01:42 PM.
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
for scroll detection, you make a control that inherits from listview, and then you override wndproc and look for WM_HSCROLL, WM_VSCROLL, or SBM_SETSCROLLINFO messages, and raise a custom event.
As far as the listviewitems being drawn transparent, I am not sure how you would accomplish that, other than setting the listview to ownerdraw, and drawing the background (cropped of course) in for each listviewitem when the call is made to repaint it. If you want to post the code you have so far, I would be willing to look into getting it to work. I am still thinking it could be a major performance hit to pull it all off, but i guess in theory its doable..
Re: [2008] Get part of background image covered by ListView control
Thank you for your help, I'll have a go at owner drawing tomorrow. Btw WM_HSCROLL, WM_VSCROLL and SBM_SETSCROLLINFO are not sent when the ListView is scrolled using the mouse wheel. But I can fix it I think.
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
I've done it, although there is quite a bit of flicker. I'm currently using a timer-stopwatch arrangement to refresh the ListView while scrolling, however this is far from perfect. I'll try and think of something to eliminate (or at least reduce) the flicker. I am currently not at liberty to post the code, however as soon as the project is finished I will do so.
Do you think that a TreeView may be modified to be translucent, just as the other controls in your articles at zerosandtheone? I tried overriding OnPaint, OnPaintBackground and setting transparent background colors, however it didn't work. If set to OwnerDraw, I'd have to draw every single node and line manually, which is not something I'd like to do. I'd prefer to crop and draw the background picture on the TreeView background if possible.
If it's too difficult with a TreeView I'd settle for a ListBox as well.
I'm trying to adapt your method with a TreeView and ListBox right now, but I'm struggling with the owner drawing...
Last edited by obi1kenobi; Jan 14th, 2009 at 07:02 AM.
Please rate helpful ppl's posts. It's the best 'thank you' you can give
Re: [2008] Get part of background image covered by ListView control
Any scrollable control is going to have issues, and the treeview is going to have many of the same hurdles as the treeview. So I would say no you can't use the articles I did for a treeview, likely you would go more along the lines of the method you used for the listview.