欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MFC 控件子类化

程序员文章站 2022-05-24 18:23:16
...

程序中用到Windows通用控件。比如按钮控件,进度条控件等等。但是有时我们需要给控件更多的特色,这就需要做控件的子类化(subclassing).
子类化,通俗来讲就是用自己的窗口处理函数来处理特定消息,并将自己其他消息还给标准(默认)窗口处理函数。在SDK中,通过SetWindowLong来指定一个自定义窗口处理函数:SetWindowLong(hwnd, GWL_WNDPROC, (LONG)UserWndProc);

_editHwnd = _editHtmlBody.GetSafeHwnd();//获得窗口对象(CWnd的派生对象)指针的句柄(HWND)
    //_lpEditProc 为内置窗口处理地址
_lpEditProc(WNDPROC)::SetWindowLong(_editHtmlBody.GetSafeHwnd(),GWLP_WNDPROC(LONG)&CTabHtmlBody::SubEditProc);
    //该函数用来改变指定窗口的属性       GWLP_WNDPROC  为窗口设定一个新的处理函数。



long CTabHtmlBody::SubEditProc(HWND hWnd,UINT uMsg,WPARAM wparam,LPARAM lparam)
{
    PAINTSTRUCT  ps;
    if(uMsg == WM_PAINT)
    {
        ::CallWindowProc(_lpEditProc,hWnd,uMsg,wparam,lparam);
        ::BeginPaint(hWnd,&ps);
        ShowLineNum(_editHwnd);      //该函数设置RichEdit控件左侧40像素显示行号
        return ::EndPaint(hWnd,&ps);
    }
    return ::CallWindowProc(_lpEditProc, hWnd, uMsg, wparam, lparam);
}


void CTabHtmlBody::ShowLineNum(HWND hEdit)
{
	RECT ClientRect;    //RechEdit客户区大小
	HDC  hdcEdit;       //RechEdit的DC
	HDC  hdcCpb;		//与RechEdit兼容的DC
	HBITMAP hdcBmp;		//与RechEdit兼容的位图dc
	int  CharHeigh;
	int  chHeigh;
	int  FirstLine;		//文本框第一个可见行的行号
	int  ClientHeigh;   //RechEdit的客户去高度
	int  LineCount;
	wchar_t  countBuf[10]; //显示行号的缓冲区
	CHARFORMAT CharFmt;

	hdcEdit = ::GetDC(hEdit);
	::GetClientRect(hEdit,&ClientRect);
	ClientHeigh = ClientRect.bottom - ClientRect.top;
	hdcCpb = ::CreateCompatibleDC(hdcEdit);
	hdcBmp = ::CreateCompatibleBitmap(hdcEdit,40,ClientHeigh);
	SelectObject(hdcCpb,hdcBmp);


	::FillRect(hdcCpb,&ClientRect,::CreateSolidBrush(0x8080ff));
	::SetBkMode(hdcCpb,TRANSPARENT);

	LineCount = ::SendMessage(hEdit,EM_GETLINECOUNT,0,0);


	RtlZeroMemory(&CharFmt,sizeof(CharFmt));
	CharFmt.cbSize = sizeof(CharFmt);

	::SendMessage(hEdit,EM_GETCHARFORMAT,TRUE,(long)&CharFmt);
	CharHeigh = CharFmt.yHeight/15;
	chHeigh = CharHeigh;
	CharHeigh = 2;

	SetTextColor(hdcCpb,0x000000);

	FirstLine = ::SendMessage(hEdit,EM_GETFIRSTVISIBLELINE,0,0);
	FirstLine++;

	while(FirstLine < LineCount)
	{
		::TextOut(hdcCpb,1, CharHeigh, countBuf,wsprintf(countBuf,L"%4u", FirstLine++));
		CharHeigh += chHeigh + 3;
		if(CharHeigh > ClientHeigh) break;
	}

	::BitBlt(hdcEdit,0,0,40,ClientHeigh,hdcCpb,0,0,SRCCOPY);
	::DeleteDC(hdcCpb);
	::ReleaseDC(hEdit,hdcEdit);
	::DeleteObject(hdcBmp);
}