Win32 Background on Edit Control

Started by
6 comments, last by TTK-Bandit 14 years, 1 month ago
Hey I'm trying to draw a background on an edit control. I've got it working til the point when the edit gets scrolled from the user. Then it will only draw on top of the previously drawn, so a blur gets drawn. When scrolled completely to the bottom however, it refreshes the complete view. My current approach does this: in the mainwindows windowproc:

		case WM_CTLCOLORSTATIC:
			if ( ( HWND ) lParam == hWndEdit ) {
				SetBkMode( ( HDC ) wParam, TRANSPARENT );
				return 0;
			}
			break;
and in the edit windows proc, I check for WM_ERASEBKGND and draw the bitmap and return 1. I guess I need to find a message that gets send to my edit control whenever it changed the scroll position. But EM_SCROLL does not get send, and WM_VSCROLL only happens when I use the mouse to move the scrollbar. I tried calling SendMessage( hWnd, WM_ERASEBKGND, (WPARAM)GetDC(hWnd), 0 ) on the WM_VSCROLL event, but that was really flickering. I tried working with WS_EX_TRANSPARENT and adding a static image behind the edit control, but for some reason, the transparent doesn't do what I thought it would. Any ideas how to make it work nicely ? All I want is a fixed size image drawn in the center of the edit control.
Advertisement
Can you post your WM_ERASEBKGND handler?
WM_CTLCOLORSTATIC should be returning a brush, not 0.

Quote:
If an application processes this message, the return value is a handle to a brush that the system uses to paint the background of the static control.

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

Quote:Original post by Rattrap
WM_CTLCOLORSTATIC should be returning a brush, not 0.

Quote:
If an application processes this message, the return value is a handle to a brush that the system uses to paint the background of the static control.

But the OP wants to have control over the background painting, no?

Also, IIRC this brush is only used for the background of the area where text can actually lie, not the entirety of the edit control.

As an aside: OP, why aren't you using WM_CTLCOLOREDIT?
	if ( uMsg == WM_ERASEBKGND ) {		// Setup Drawing		HDC hdc = (HDC)wParam;		HDC hcompdc = CreateCompatibleDC(hdc);		// Get area to draw		RECT destRect;		GetClientRect(hWnd, &destRect);		// Fill the background		FillRect( hdc, &destRect, hbrEditBg );		// find the center rect		destRect.left += (destRect.right - destRect.left)/2 - wcd.bgImgWidth/2;		destRect.top += (destRect.bottom - destRect.top)/2 - wcd.bgImgHeight/2;		RECT srcRect = { 0, 0, bgImgWidth, bgImgHeight };		// Adjust source and destination rect, if out of bounds		if ( destRect.top < 0 ) {			srcRect.top = -destRect.top;			srcRect.bottom -= -2*destRect.top;			destRect.top = 0;		}		if ( destRect.left < 0 ) {			srcRect.left = -destRect.left;			srcRect.right -= -2*destRect.left;			destRect.left = 0;		}		// Draw the image		SelectObject(hcompdc, hBackBmp);		StretchBlt(hdc, destRect.left, destRect.top, srcRect.right, srcRect.bottom,			hcompdc, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, SRCCOPY);		DeleteDC(hcompdc);		return 1;	}


Rattrap: doesn't matter, it does the same as creating a HOLLOW_BRUSH
Quote:As an aside: OP, why aren't you using WM_CTLCOLOREDIT?


it's a read-only control, those call WM_CTLCOLORSTATIC instead of WM_CTLCOLOREDIT
I knew of an old Article on how to display an Image on the Background of a Richedit Control. I think it was on codeproject.
It is not an easy Task. There is a lot of incremental painting in both Edit and Richedit controls. The best long term Solution is to create your own custom Control.
got it working using richedit:
::LoadLibrary(L"Riched20.dll");hWndEdit = CreateWindowEx(WS_EX_TRANSPARENT, L"RICHEDIT20W", L"",			WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER | ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL,			0, 0, 0, 0, hWndMain, MY_EDIT_ID, hInstance, NULL );

then subclass the window and do:
	if ( uMsg == WM_ERASEBKGND ) {		// Setup Drawing		HDC hdc = (HDC)wParam;		HDC hcompdc = CreateCompatibleDC(hdc);		// Get area to draw		RECT destRect, wndRect;		GetClientRect(hWndEdit, &wndRect);		GetClientRect(hWndEdit, &destRect);		// find the center rect		destRect.left += (destRect.right - destRect.left)/2 - bgImgWidth/2;		destRect.top += (destRect.bottom - destRect.top)/2 - bgImgHeight/2;		RECT srcRect = { 0, 0, bgImgWidth, bgImgHeight };		// Adjust source and destination rect, if out of bounds		if ( destRect.top < 0 ) {			srcRect.top = -destRect.top;			srcRect.bottom -= -2*destRect.top;			destRect.top = 0;		}		if ( destRect.left < 0 ) {			srcRect.left = -destRect.left;			srcRect.right -= -2*destRect.left;			destRect.left = 0;		} else {			RECT tRect = { 0, 0, destRect.left, wndRect.bottom };			FillRect( hdc, &tRect, hbrEditBg );		}		destRect.right =  destRect.left + srcRect.right;		destRect.bottom =  destRect.top + srcRect.bottom;		if ( destRect.right < wndRect.right ) {			RECT tRect = { destRect.right, 0, wndRect.right, wndRect.bottom };			FillRect( hdc, &tRect, hbrEditBg );		}		if ( destRect.left > 0 ) {			RECT tRect = { destRect.left, 0, destRect.right, destRect.top };			FillRect( hdc, &tRect, hbrEditBg );		}		if ( destRect.bottom < wndRect.bottom ) {			RECT tRect = { destRect.left, destRect.bottom, destRect.right, wndRect.bottom };			FillRect( hdc, &tRect, hbrEditBg );		}		// Draw the image		SelectObject(hcompdc, hBackBmp);		BitBlt(hdc, destRect.left, destRect.top, srcRect.right, srcRect.bottom, hcompdc, srcRect.left, srcRect.top, SRCCOPY);		DeleteDC(hcompdc);		return 1;	}

One might wonder why I call fillrect 4 times instead of once for the whole background, that is to avoid flickering.

This topic is closed to new replies.

Advertisement