[WTL/ATL]_[初级]_[如何设置CEdit的文本框背景色和文字颜色]

场景

  1. 在开发WTLMFC界面程序时,经常会使用CEdit文本框,但是有时候为了和父窗口的颜色对应上,文本框里的背景色也需要和父窗口一样。CEdit或者说EditWin32控件[4]并没有相应的方法或者消息WM_XX来设置背景色的值,怎么办?

说明

  1. Edit控件的官方说明, 当不是禁用或者只读时使用WM_CTLCOLOREDIT消息来改变控件的文本和背景色(当禁用和只读时使用WM_CTLCOLORSTATIC消息来处理)。父窗口通过指定设备的上下文句柄HDC来改变颜色。
An edit control that is not read-only or disabled sends the WM_CTLCOLOREDIT message to its parent window when the control is about to be drawn. By responding to this message, the parent window can use the specified device context handle to set the text and background colors of the edit control. 
  1. 相关改变颜色的函数就是以下两个函数,当然还需要返回一个HBRUSH作为窗口背景色. SetBkColor只是文字的背景色,它的区域是比CEdit的窗口区域小的。

    LRESULT CView::OnCtlColor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
    	HWND hWnd = (HWND)lParam;
    	HDC hdc = (HDC)wParam;
    	
    	//1. 只改变多行`Edit`的文本框窗口颜色和文本背景底色.
    	if(hWnd == *editMultiLine_){
    		CDCHandle dc(hdc);
    		dc.SetBkColor(RGB(255,0,0));
    		dc.SetTextColor(RGB(0,0,255));
    		return (LRESULT)AtlGetStockBrush(WHITE_BRUSH);
    	}
    
    	//2. 其他`Edit`的消息不处理
    	bHandled = FALSE;
    	return 0;
    }
    
  2. 在消息映射宏里添加对WM_CTLCOLOREDITWM_CTLCOLORSTATIC消息的捕抓.

    BEGIN_MSG_MAP_EX(CView)
    	MSG_WM_CREATE(onCreate)
    	MESSAGE_HANDLER(WM_PAINT, onPaint)
    	MESSAGE_HANDLER(WM_CTLCOLOREDIT, OnCtlColor)
    	MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnCtlColor)
    	REFLECT_NOTIFICATIONS()
    END_MSG_MAP()
    
  3. 如果是自定义的CEdit子控件,可以通过转发的WM_CTLCOLOREDIT消息来处理这个背景色,并提供setBkgColor()方法即可.

class BASEdit : public CWindowImpl<BASEdit, CEdit>
{
public:
	BASEdit();
	~BASEdit();
    BEGIN_MSG_MAP_EX(BASEdit)
		MSG_OCM_CTLCOLOREDIT(OnReflectedCtlColorEdit)
		MSG_WM_KEYDOWN(OnKeyDown)
        DEFAULT_REFLECTION_HANDLER()
    END_MSG_MAP()
 
	void setBkgColor(COLORREF color);
	void setTextColor(COLORREF color);
    ...
};
#define OCM_CTLCOLOREDIT    (OCM__BASE + WM_CTLCOLOREDIT)

例子

  1. 一下例子使用和原CEdit和子类的BASEdit达到修改文本框背景色和文字颜色的效果。

View.h

// View.h : interface of the CView class
//
/

#ifndef VIEW_H
#define VIEW_H

class BASEdit;

typedef enum ViewWindowId1 {
	kViewWindowEditId = WM_USER + 1000,
	kViewWindowEditMultiLineId
}ViewWindowId;

class CView : public CWindowImpl<CView>
{
public:
	DECLARE_WND_CLASS(NULL)

	BOOL PreTranslateMessage(MSG* pMsg);

	BEGIN_MSG_MAP_EX(CView)
		MSG_WM_CREATE(onCreate)
		MESSAGE_HANDLER(WM_PAINT, onPaint)
		MESSAGE_HANDLER(WM_CTLCOLOREDIT, OnCtlColor)
		MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnCtlColor)
		REFLECT_NOTIFICATIONS()
	END_MSG_MAP()

// Handler prototypes (uncomment arguments if needed):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)

protected:
	LRESULT OnCtlColor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT onPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	int onCreate(LPCREATESTRUCT lpCreateStruct);
	void onEnter();

private:
	BASEdit* edit_;
	CEdit* editMultiLine_;
};

#endif

View.cpp

// View.cpp : implementation of the CView class
//
/

#include "stdafx.h"
#include "resource.h"

#include "View.h"
#include "base/bas_edit.h"
#include <functional>

static LRESULT CALLBACK Edit_Prc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{
	if (msg == WM_CHAR && wParam == 1){
		SendMessage(hwnd, EM_SETSEL, 0, -1);
		return 1;
	}

	auto oldProc = (WNDPROC)GetWindowLong(hwnd, GWL_USERDATA);
	return CallWindowProc(oldProc, hwnd, msg, wParam, lParam);
}


BOOL CView::PreTranslateMessage(MSG* pMsg)
{
	pMsg;
	return FALSE;
}

void CView::onEnter()
{
	auto length = edit_->GetWindowTextLength()+1;
	auto buf = new wchar_t[length]();
	edit_->GetWindowText(buf,length);

	MessageBox(buf);
}

LRESULT CView::OnCtlColor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	HWND hWnd = (HWND)lParam;
	HDC hdc = (HDC)wParam;
	
	//1. 只改变多行`Edit`的文本框窗口颜色和文本背景底色.
	if(hWnd == *editMultiLine_){
		CDCHandle dc(hdc);
		dc.SetBkColor(RGB(255,0,0));
		dc.SetTextColor(RGB(0,0,255));
		return (LRESULT)AtlGetStockBrush(WHITE_BRUSH);
	}

	//2. 其他`Edit`的消息不处理
	bHandled = FALSE;
	return 0;
}

int CView::onCreate(LPCREATESTRUCT lpCreateStruct)
{
	edit_ = new BASEdit();
	edit_->Create(m_hWnd, CRect(CPoint(100,100),CSize(200,30)), 0, 
		WS_CHILD|WS_VISIBLE|WS_BORDER, 0,kViewWindowEditId);
	
	function<void()> funcEnter = bind(&CView::onEnter, this);
	edit_->setFuncEnterCallback(funcEnter);
	edit_->SetCueBannerText(L"Date: 2021-04-28",true);
	edit_->setBkgColor(RGB(0,0,255));
	edit_->setTextColor(RGB(255,255,255));

	editMultiLine_ = new CEdit();
	editMultiLine_->Create(m_hWnd, CRect(CPoint(100, 200), CSize(200, 30)), 0, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL, 0,
		kViewWindowEditMultiLineId);
	auto oldProc = editMultiLine_->SetWindowLong(GWL_WNDPROC, (LONG)Edit_Prc);
	editMultiLine_->SetWindowLong(GWL_USERDATA, (LONG)oldProc);

	return 0;
}

LRESULT CView::onPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	CPaintDC dc(m_hWnd);

	//TODO: Add your drawing code here

	return 0;
}

BASEdit.h


#ifndef __BAS_EDIT
#define __BAS_EDIT

#include <Windows.h>

#include <GdiPlus.h>
#include <string>
#include <memory>
#include <functional>
#include "atlcrack.h"

using namespace std;

class BASEdit : public CWindowImpl<BASEdit, CEdit>
{
public:
	BASEdit();
	~BASEdit();
    BEGIN_MSG_MAP_EX(BASEdit)
		MSG_OCM_CTLCOLOREDIT(OnReflectedCtlColorEdit)
		MSG_WM_KEYDOWN(OnKeyDown)
        DEFAULT_REFLECTION_HANDLER()
    END_MSG_MAP()
 
	void setFuncEnterCallback(function<void()>& func);
	void setBkgColor(COLORREF color);
	void setTextColor(COLORREF color);

protected:

	HBRUSH OnReflectedCtlColorEdit(CDCHandle dc, HWND edit);
	void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);

private:
	function<void()> funcEnterCallback_;
	HBRUSH brushBkg_;
	COLORREF colorBkg_;
	COLORREF colorFont_;
};

#endif

BASEdit.cpp

#include "stdafx.h"
#include "bas_edit.h"

#include <iostream>

using namespace std;

BASEdit::BASEdit()
{
	colorBkg_ = GetSysColor(COLOR_WINDOW);
	colorFont_ = GetSysColor(COLOR_WINDOWTEXT);;
	brushBkg_ = ::CreateSolidBrush(colorBkg_);
}

BASEdit::~BASEdit()
{
	::DeleteObject(brushBkg_);
}

void BASEdit::setBkgColor(COLORREF color)
{
	colorBkg_ = color;
	::DeleteObject(brushBkg_);
	brushBkg_ = ::CreateSolidBrush(colorBkg_);
}

void BASEdit::setTextColor(COLORREF color)
{
	colorFont_ = color;
}

void BASEdit::setFuncEnterCallback(function<void()>& func)
{
	funcEnterCallback_ = func;
}

void BASEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	if (nChar == VK_RETURN) {
		if (funcEnterCallback_)
			funcEnterCallback_();
	}
	else {
		SetMsgHandled(FALSE);
	}	
}

HBRUSH BASEdit::OnReflectedCtlColorEdit(CDCHandle dc, HWND edit)
{
	::SetBkColor(dc,colorBkg_);
	::SetTextColor(dc,colorFont_);
	return brushBkg_;
}

运行

图1
在这里插入图片描述

下载

https://download.csdn.net/download/infoworld/85143035

参考

  1. win32 api and changing the color od a edit box

  2. How do I change the background of a STATIC win32 control

  3. WM_CTLCOLOREDIT

  4. Edit Control

  5. 使用WTL进行Windows桌面应用开发-1

  6. 使用WTL进行Windows桌面应用开发-2

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Peter(阿斯拉达)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值