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

Posted infoworld

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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

以上是关于[WTL/ATL]_[初级]_[如何设置CEdit的文本框背景色和文字颜色]的主要内容,如果未能解决你的问题,请参考以下文章

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

[WTL/ATL]_[初级]_[TreeView控件如何显示ToolTip]

[WTL/ATL]_[初级]_[微调控件CUpDownCtrl的使用]

[WTL/ATL]_[初级]_[关于窗口子类析构时崩溃的原因]

[WTL/ATL]_[初级]_[使用虚拟列表视图来解决新增大量数据卡顿问题]

[WTL/ATL]_[初级]_[使用虚拟列表视图来解决新增大量数据卡顿问题]