C# Tutorials and offshore development in India
    Tutorials   Resources   Forum   Reviews   Communities   Interview   Jobs   Projects   Training   Your Ad Here    
Silverlight Games | Mentor | Code Converter | Articles | Code Factory | Computer Jokes | Members | Peer Appraisal | IT Companies | Bookmarks | Polls | Revenue Sharing | Lobby | Gift Shop |


Prizes & Awards
My Profile



Active Members
TodayLast 7 Days more...






Resources » Articles » .NET Framework »

Displaying Background Images in Listbox and TextBox


Posted Date: 08 May 2004    Resource Type: Articles    Category: .NET Framework
Author: sanyam aggarwalMember Level: Bronze    
Rating: 1 out of 5Points: 10



Subclassing a Listbox to Display an Image in Background
by Sanyam Aggarwal

This article assumes that you are familiar with subclassing-if you want to start off with subclassing read the artice previously submitted by me. Though this article user VB 6.0, concepts learned from this can easily be applied to .NET projects.

The key to subclassing a ListBox to display an Image in its background is WM_CTLCOLORLISTBOX event send by the Windows to the parent form of Listbox.
By responding to this message, the parent window can set the text and background colors of the list box by using the given display device context handle.

The wParam parameter contains the handle to device context for the list box whereas lParam is the handle of the Listbox itself. If an application processes this message, it must return a handle to a brush. The system uses the brush to paint the background of the list box. This is our opportunity, we have to return the brush for painting the listbox so we can set a custom brush and operating system will use it to draw contents on the Listbox.

The SetBkMode function which we will be using in our example program sets the background mix mode of the specified device context. The background mix mode is used with text, hatched brushes, and pen styles that are not solid lines. We must set the background mode of the listbox to transparent otherwise results will not be pleasant, though the picture will be displayed correctly, the Items will appear against a white background thus spoiling the whole effect. Also we need the InvalidateRect function.
The InvalidateRect function adds a rectangle to the specified window's update region. The update region represents the portion of the window's client area that must be redrawn.
It accepts a handle to window whose region is to be updated and a rectangle structure which represents the regoin to add to update region. If we pass 0 as update region, whole regoin is caused to be updated. Alright, but why do we need this? Just to prevent flickering which occurs when the Listbox is scrolled.

Finally we need the CreatePatternBrush API function which creates a logical brush with the specified bitmap pattern. It return the handle to the Brush created. So if you want that you Listbox should have somePic.bmp as its background, all you need is to load this picture in ImageBox and get a handle to the Brush like this:

hBrush=CreatePatternBrush(Image1.picture.handle)

Thats it! You are now ready for the Code sample:

1)Open a new Standard EXE project. Add a listbox named List1. Also add an Image control Image1 and load in it the Image you want to use as the background for your ListBox.

2)Add a Bas Module and add the Following Code:


Option Explicit

Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long

Private Declare Function InvalidateRect Lib "user32" (ByVal hwnd As Long, _
ByVal lpRect As Long, ByVal bErase As Long) As Long

Public Declare Function CreatePatternBrush Lib "gdi32" (ByVal hBitmap As Long) _
As Long

Private Declare Function SetBkMode Lib "gdi32" (ByVal hdc As Long, ByVal nBkMode As Long) _
As Long

Private Const WM_CTLCOLOREDIT = &H133
Private Const WM_CTLCOLORLISTBOX = &H134
Private Const WM_VSCROLL = &H115
Private Const WM_ERASEBKGND = &H14
Public Const GWL_WNDPROC = (-4)

Public hBrush As Long
Public prevFuncPointer As Long
Public prevListboxFuncPointer As Long

Public Function frmWndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long

If (uMsg = WM_CTLCOLORLISTBOX) And hBrush <> 0 Then
' Make the words print transparently
SetBkMode wParam, 1

' Allow the original process to set text color, etc. from the lbx properties.
CallWindowProc prevFuncPointer, hwnd, uMsg, wParam, lParam

' Return our custom brush instead of the default one
frmWndProc = hBrush
Else
frmWndProc = CallWindowProc(prevFuncPointer, hwnd, uMsg, wParam, lParam)
End If
End Function

Public Function lbWndProc(ByVal hwnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long

' Force the control to repaint itself every time the scroll message is received.

If uMsg = WM_VSCROLL Then
' Force windows to repaint the listbox
InvalidateRect hwnd, 0, 0

' Invoke the default process
lbWndProc = CallWindowProc(prevListboxFuncPointer, hwnd, uMsg, wParam, lParam)

ElseIf uMsg = WM_ERASEBKGND Then
' Don't return anything. Processing the default routine will actually cause
' flickering when' scrolling.
lbWndProc = 1
Else
' Invoke the default process
lbWndProc = CallWindowProc(prevListboxFuncPointer, hwnd, uMsg, wParam, lParam)
End If

End Function


3)To the Form, add the following code:


Private Sub Form_Load()
'Add items to Listbox at RUN TIME ONLY!
dim i as integer
For i=0 to 100
list1.AddItem "Item# " & i
Next
' create a brush from specified image.(Image1 must be there!)
hBrush = CreatePatternBrush(Image1.Picture.Handle) '

' Subclass the window
prevFuncPointer = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf frmWndProc)

prevListBoxFuncPointer = SetWindowLong(List1.hwnd, GWL_WNDPROC, AddressOf lbWndProc)
End Sub

Private Sub Form_Unload(Cancel As Integer)
' Unsubclass (return the original processes)
SetWindowLong Me.hwnd, GWL_WNDPROC, prevFuncPointer
SetWindowLong List1.hwnd, GWL_WNDPROC, prevListBoxFuncPointer
End Sub


CAUTION:
When you use this technique to Display Images in BackGround, YOU MUST ADD ALL ELEMENTS AT RUNTIME OTHERWISE UNEXPECTED RESULTS MAY OCCUR!

Now with this Caution comes a Good news:

Wanted to Display Images in background of TextBoxes and RichTextBoxes so as to Customize their apperance?

If yes, you have already learnt so! Believe me the Technique is really the same, you just have to find it out. It is unbeleivable same!

So look for it!!

HINT: Look for WM_CTLCOLOREDIT in MSDN Documentation.









Responses

Author: Kanya    27 May 2004Member Level: Bronze   Points : 0
I am getting error for
1)'hwnd' is not a member of 'Images.Form1'.
2)for windows form I tried Imagelist/Picture box-giving error as Value of type 'System.IntPtr' cannot be converted to 'Long'.




Author: sanyam aggarwal    31 May 2004Member Level: Bronze   Points : 0
Use handle.ToInt32 Method wherever they need a handle to the Form.

Convert System.InPtr to long using System.InPtr32.ToInt32 and then pass them to API declarations.

Hope this will solve your problem.


Author: Thangavel Rajan    21 Aug 2006Member Level: Bronze   Points : 0
Hi,

While i am trying in VB.net, I am getting this error :
'AddressOf' expression cannot be converted to 'Long' because 'Long' is not a delegate type.

Thangavel



Feedbacks      
Popular Tags   What are tags ?   Search Tags  
Sign In to add tags.
(No tags found.)

Post Feedback


This is a strictly moderated forum. Only approved messages will appear in the site. Please use 'Spell Check' in Google toolbar before you submit.
You must Sign In to post a response.
Next Resource: The Preprocessor Directives in C#
Previous Resource: Show or Hide the Start Button of TaskBar
Return to Discussion Resource Index
Post New Resource
Category: .NET Framework


Post resources and earn money!
 
Related Resources



dotNet Slackers

About Us    Contact Us    Privacy Policy    Terms Of Use