How to subclass a gui control?

Leonardo 96 Reputation points
2022-08-22T03:41:33.69+00:00

Im trying to learn how to 'properly' subclass a GUI control and repaint her hdc.
This is my subclass callback:

LRESULT CALLBACK ButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)  
{  
	Gui* pThis = (Gui*)dwRefData;  
  
	switch (uMsg)  
	{  
	case WM_ERASEBKGND:  
	{  
		if (pThis->control_list[hWnd].ERASEDBKGND)  
			return 1;  
  
		// Create/save the new button dc.  
		GpBitmap* pBitmap;  
		GdipCreateBitmapFromScan0(pThis->control_list[hWnd].width, pThis->control_list[hWnd].height, 0, PixelFormat32bppPARGB, 0, &pBitmap);  
  
		GpGraphics* g;  
		GdipGetImageGraphicsContext(pBitmap, &g);  
		GdipGraphicsClear(g, 0xFF2400ff);  
  
		HBITMAP hbm;  
		GdipCreateHBITMAPFromBitmap(pBitmap, &hbm, 0);  
  
		HDC dc = CreateCompatibleDC(NULL);  
		SelectObject(dc, hbm);  
  
		pThis->control_list[hWnd].dc = dc;  
  
		GdipDisposeImage(pBitmap);  
		GdipDeleteGraphics(g);  
		DeleteObject(hbm);  
		//DeleteObject(dc);  
  
		pThis->control_list[hWnd].ERASEDBKGND = 1;  
	}  
	break;  
  
	case WM_LBUTTONDBLCLK:  
	case WM_LBUTTONDOWN:  
	{  
		InvalidateRect(hWnd, 0, 1);  
	}  
	break;  
  
	case WM_PAINT:  
	{  
		PAINTSTRUCT ps;  
		HDC hdc = BeginPaint(hWnd, &ps);  
  
		BLENDFUNCTION bf;  
		bf.SourceConstantAlpha = 255;  
		bf.BlendOp = AC_SRC_OVER;  
		bf.BlendFlags = 0;  
		bf.AlphaFormat = AC_SRC_ALPHA;  
  
		GdiAlphaBlend(hdc, 0, 0, pThis->control_list[hWnd].width, pThis->control_list[hWnd].height,  
			pThis->control_list[hWnd].dc, 0, 0, pThis->control_list[hWnd].width, pThis->control_list[hWnd].height, bf);  
  
		//BitBlt(hdc, 0, 0, pThis->control_list[hWnd].width, pThis->control_list[hWnd].height,  
		//	pThis->control_list[hWnd].dc, 0, 0, SRCCOPY);  
  
		EndPaint(hWnd, &ps);  
		DeleteObject(hdc);  
		return TRUE;  
	}  
	break;  
  
	}  
	return DefSubclassProc(hWnd, uMsg, wParam, lParam);  
}  

The problem is... when i click into the button it restores her default dc:
233306-2022-08-21-23-59-07.gif

I have added a call to InvalidateRect upon clicking on it, but it remains the same thing.
I also tried creating the Gui with the double buffering styles (WS_EX_COMPOSITED | WS_EX_LAYERED).

What im missing?

The project: https://1drv.ms/u/s!An5RIz0rv2kIhk9WnHOFze6avT6N?e=umyLn4

Windows development | Windows API - Win32
Developer technologies | C++
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Castorix31 90,681 Reputation points
    2022-08-22T06:36:18.1+00:00

    It depends on the control class and C.C. version
    For Buttons, all the drawing is done in WM_PAINT, by checking the different states (if themed, PBS_HOT, PBS_PRESSED, etc...)
    but you must set C.C v6, like :

    #pragma comment(linker,"\"/manifestdependency:type='win32' \  
    name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \  
    processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")  
    

    (if I just draw a red rectangle in WM_PAINT only, it overwrites all the default drawing)

    (and for Buttons, it is simpler to use Owner-Drawn (Custom Controls))


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.