如何在鼠标悬停时绘制文本控件?
How to paint a text control on mouse hover?
我在绘制静态文本控件时遇到问题。我已经阅读了一些有关此事的资料,也尝试了一些代码,但其中 none 行得通。我设法得到的最接近的是直到文本控件检测到我的鼠标悬停事件。为此,我使用控件子类化。但是,我不知道如何在鼠标悬停时绘制文本控件。
我的问题是:
我很困惑是把负责绘制文本控件的代码放在子类的WM_MOUSEMOVE
还是WM_MOUSEHOVER
中。原因是因为在 WM_MOUSEMOVE
中,我设置了当文本控件的矩形区域检测到光标时,应该进行绘制。同时,我觉得很奇怪,因为 WM_MOUSEHOVER
不应该已经完成了那个特定角色吗?
我真的需要有关如何在鼠标悬停时突出显示文本控件的帮助。
// global text control handler
HWND txtHwnd; //somewhere in the global area of codes
//class for mouse event tracking
class MouseTrackEvents
{
bool m_bMouseTracking;
public:
MouseTrackEvents() : m_bMouseTracking(false) {}
void OnMouseMove(HWND hwnd)
{
if (!m_bMouseTracking)
{
// Enable mouse tracking.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER;
tme.dwHoverTime = 100; //0.1s
TrackMouseEvent(&tme);
m_bMouseTracking = true;
}
}
void Reset(HWND hwnd)
{
m_bMouseTracking = false;
}
};
//subclass proc for text control
LRESULT CALLBACK OwnerTxtProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
//local mouse track object
MouseTrackEvents mouseTrack;
const int numOfMsg = 4;
int myMsgBox[numOfMsg]; //limit to only 4
HBRUSH hbrBkgndA = CreateSolidBrush(RGB(0, 255, 0));
//just want to print what wparam is..
int wmId, wmEvent;
wchar_t wParamHI[1000];
wchar_t wParamLO[1000];
//for painting
COLORREF hbrHighlight;
//HBRUSH hbrHighlight;
HDC txtHDC;
RECT txtRect;
POINT txtPt;
RECT txtRt;
switch (uMsg) {
case WM_CREATE: {
//testing purposes
myMsgBox[0] = MessageBox(nullptr, L"Yessir!", L":D", MB_OK | MB_ICONINFORMATION);
break;
}
case WM_MOUSEMOVE: {
mouseTrack.OnMouseMove(hWnd); //activate mouse tracking
GetWindowRect(hWnd, &txtRt); //see what value lies within
GetCursorPos(&txtPt);
if (PtInRect(&txtRt, txtPt)) {
//to check whether cursor is in text rect or not
MessageBox(nullptr, L"Okea..nice..!", L":D", MB_OK | MB_ICONINFORMATION);
//i dont know what to do here
//i was thinking that painting should be placed here...
//HBRUSH hbrBkgndEdit = CreateSolidBrush(RGB(100, 100, 255));
}
else {
//to check whether cursor is in text rect or not
MessageBox(nullptr, L"Oh noooo!", L":D", MB_OK | MB_ICONINFORMATION);
}
break;
}
case WM_MOUSEHOVER: {
//do something when txt ctrl is hovered
//to test whether wm_mousehover works, and the text control is mouse hovered
//myMsgBox[1] = MessageBox(nullptr, L"Yahooooo!", L":D", MB_OK | MB_ICONINFORMATION);
OutputDebugString(L"--------------This text control is being hovered---------------\n");
//testing painting when hovered
//plan is to send message to hChild to manage the painting since it is the parent window
//HDC theHDC = (HDC)wParam;
//SendMessage(hWnd, WM_CTLCOLORSTATIC, (WPARAM)theHDC, (LPARAM)txtHwnd);
//SendMessage(hWnd, WM_CTLCOLORSTATIC, (WPARAM)theHDC, lParam);
//for painting
//hbrHighlight = (COLORREF)(GetSysColor(COLOR_HIGHLIGHT));
//HDC hdcStatic = (HDC)wParam;
////SetTextColor(hdcStatic, RGB(0, 0, 0));
//SetBkColor(hdcStatic, hbrHighlight);
//for painting II
//HDC txtCtrlMe = (HDC)wParam;
//SetTextColor(txtCtrl, RGB(0, 0, 0));
//SetBkColor(txtCtrlMe, RGB(0, 255, 0));
//SendMessage(hChild, WM_CTLCOLORSTATIC, (WPARAM)txtCtrlMe, (LPARAM)txtHwnd);
//DeleteBrush(hbrBkgndA);
mouseTrack.Reset(hWnd);
//return (INT_PTR)hbrHighlight;
//mouseTrack.Reset(hWnd);
break;
//return TRUE;
}
//case WM_CTLCOLORSTATIC:
//{
// HDC txtCtrlMe = (HDC)wParam;
// //SetTextColor(txtCtrl, RGB(0, 0, 0));
// SetBkColor(txtCtrlMe, RGB(0, 255, 0));
// if (hbrBkgndA == NULL)
// {
// hbrBkgndA = CreateSolidBrush(RGB(255, 255, 255)); //eqivalent to delete brush objet
// }
// return (INT_PTR)hbrBkgndA;
// //break;
//}
//painting
/*
SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
SendMessage(hChild, WM_CTLCOLORSTATIC, (WPARAM)txtCtrlMe, (LPARAM)txtHwnd);
*/
//you can just ignore this, this is just for me to see whats inside wParam of the subclass
case WM_LBUTTONDOWN: {
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
int HI = swprintf_s(wParamHI, 1000, L"wParamHI: %d", wmEvent);
MessageBox(nullptr, wParamHI, L":D", MB_OK | MB_ICONINFORMATION);
int LO = swprintf_s(wParamLO, 1000, L"wParamLO: %d", wmId);
MessageBox(nullptr, wParamLO, L":D", MB_OK | MB_ICONINFORMATION);
break;
}
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
//child window proc, which contains the static text control
LRESULT CALLBACK WndProcChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
//...some other codes...
txtHwnd = CreateWindow(L"Static", L"Hello World!", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 100, 100, 120, 15, hChild, (HMENU)testingTxtID, nullptr, nullptr);
//control subclassing
//a.k.a attaching subclass proc to the static text control
SetWindowSubclass(txtHwnd, OwnerTxtProc, 0, 0);
//...some other codes...
default: {
return DefWindowProc(hChild, message, wParam, lParam);
}
return 0;
}
请忽略我在WM_MOUSEHOVER
和WM_CTLCOLORSTATIC
中注释掉的代码OwnerTxtProc(...)
。它们只是我用来尝试绘制文本控件的代码,但没有用。
您的控件的所有绘制操作都应该只在 WM_CTLCOLORSTATIC
处理程序内,甚至 WM_PAINT
处理程序内。
要触发控件的重绘,只需使用 InvalidateRect()
.
使控件的工作区无效即可
如果要更改绘制条件,请将相关信息存储在绘制代码使用的变量中,然后在使控件失效之前更新这些变量。
尝试这样的事情:
HWND txtHwnd;
bool bMouseTracking = false;
COLORREF bkgndColor = ...; // whatever you want...
COLORREF txtColor = ...; // whatever you want...
HBRUSH hbrBkgnd = nullptr;
const UINT APP_CTLCOLORSTATIC = WM_APP + 1;
LRESULT CALLBACK StaticTxtProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
switch (uMsg) {
case WM_NCDESTROY: {
RemoveWindowSubclass(hWnd, StaticTxtProc, uIdSubclass);
if (hbrBkgnd) {
DeleteBrush(hbrBkgnd);
hbrBkgnd = NULL;
}
bMouseTracking = false;
break;
}
case WM_MOUSEMOVE: {
if (!bMouseTracking) {
TRACKMOUSEEVENT tme = {};
tme.cbSize = sizeof(tme);
tme.hwndTrack = hWnd;
tme.dwFlags = TME_HOVER;
tme.dwHoverTime = 100; //0.1s
bMouseTracking = TrackMouseEvent(&tme);
}
RECT txtRt;
GetWindowRect(hWnd, &txtRt);
POINT txtPt;
GetCursorPos(&txtPt);
if (PtInRect(&txtRt, txtPt)) {
bkgndColor = ...; // whatever you want...
txtColor = ...; // whatever you want...
InvalidateRect(hWnd, NULL, TRUE);
}
break;
}
case WM_MOUSEHOVER: {
mMouseTracking = false;
bkgndColor = ...; // whatever you want...
txtColor = ...; // whatever you want...
InvalidateRect(hWnd, NULL, TRUE);
break;
}
case APP_CTLCOLORSTATIC: {
HDC hdc = reinterpret_cast<HDC>(wParam);
SetTextColor(hdc, txtColor);
SetBkColor(hdc, bkgndColor);
if (hbrBkgnd)
DeleteBrush(hbrBkgnd);
hbrBkgnd = CreateSolidBrush(bkgndColor);
return reinterpret_cast<LRESULT>(bkgndColor);
}
case WM_LBUTTONDOWN: {
// ...
break;
}
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK WndProcChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE: {
bkgndColor = ...; // whatever you want...
txtColor = ...; // whatever you want...
txtHwnd = CreateWindow(L"Static", L"Hello World!", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 100, 100, 120, 15, hChild, (HMENU)testingTxtID, nullptr, nullptr);
SetWindowSubclass(txtHwnd, StaticTxtProc, 0, 0);
break;
}
case WM_CTLCOLORSTATIC: {
return SendMessage(reinterpret_cast<HWND>(lParam), APP_CTLCOLORSTATIC, wParam, 0);
}
//...some other codes...
default: {
return DefWindowProc(hChild, message, wParam, lParam);
}
}
return 0;
}
(代答题者贴出答案移至答案space).
我设法解决了我在这件事上的问题。
//global variable(s)
COLORREF bkgndColor;
COLORREF txtColor;
HBRUSH hbrBkgnd = nullptr;
const UINT APP_CTLCOLORSTATIC = WM_APP + 1;
//class for mouse event
class MouseTrackEvents
{
bool m_bMouseTracking;
public:
MouseTrackEvents() : m_bMouseTracking(false) {}
void OnMouseMove(HWND hwnd)
{
if (!m_bMouseTracking)
{
// Enable mouse tracking.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = 10; //1ms
TrackMouseEvent(&tme);
m_bMouseTracking = true;
}
}
void Reset(HWND hwnd)
{
m_bMouseTracking = false;
}
};
//proc for static text contorl subclass
LRESULT CALLBACK OwnerTxtProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
//local mouse track variable
MouseTrackEvents mouseTrack;
RECT txtRt;
GetWindowRect(hWnd, &txtRt);
POINT txtPt;
GetCursorPos(&txtPt);
switch (uMsg) {
//...some other codes...
case WM_NCDESTROY: {
RemoveWindowSubclass(hWnd, OwnerTxtProc, uIdSubclass);
if (hbrBkgnd) {
DeleteBrush(hbrBkgnd);
hbrBkgnd = NULL;
}
mouseTrack.Reset(hWnd);
break;
}
case WM_MOUSEMOVE: {
mouseTrack.OnMouseMove(hWnd); //activate mouse tracking
break;
}
case WM_MOUSEHOVER: {
if (PtInRect(&txtRt, txtPt)) {
OutputDebugString(L"--------------This text control is being hovered---------------\n");
bkgndColor = RGB(0, 0, 200); // blue
txtColor = RGB(200, 0, 0); // red
InvalidateRect(hWnd, NULL, FALSE);
}
else {
OutputDebugString(L"--------------This text control is being left---------------\n");
bkgndColor = RGB(100, 0, 0); // red bg
txtColor = RGB(0, 100, 0); // green txt
InvalidateRect(hWnd, NULL, FALSE);
}
mouseTrack.Reset(hWnd);
break;
}
case WM_MOUSELEAVE: {
if (!(PtInRect(&txtRt, txtPt))) {
OutputDebugString(L"--------------This text control is being hovered---------------\n");
bkgndColor = RGB(100, 0, 0); // red bg
txtColor = RGB(0, 100, 0); // green txt
InvalidateRect(hWnd, NULL, FALSE);
}
mouseTrack.Reset(hWnd);
break;
}
case APP_CTLCOLORSTATIC: {
HDC hdc = reinterpret_cast<HDC>(wParam);
SetTextColor(hdc, txtColor);
SetBkColor(hdc, bkgndColor);
if (hbrBkgnd) {
DeleteBrush(hbrBkgnd);
}
hbrBkgnd = CreateSolidBrush(bkgndColor);
//return reinterpret_cast<LRESULT&>(bkgndColor); //--> error --> so i added '&'
return (LRESULT)hbrBkgnd;
}
//...some other codes...
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
//parent of static text control
LRESULT CALLBACK WndProcChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//...some other codes...
switch (message)
{
case WM_CTLCOLORSTATIC:
{
return SendMessage(reinterpret_cast<HWND>(lParam), APP_CTLCOLORSTATIC, wParam, 0);
}
case WM_CREATE: //put all sorts of stuff when the context menu is called
{
//font to be set to
hFont = CreateFont(17, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Segoe UI"));
//set font of the textCtrl
//doesnt work if handler target = hChild
for (int i = 0; i < textCtrlSize; i++) {
SendMessage(textCtrl[i], WM_SETFONT, (WPARAM)hFont, TRUE);
}
bkgndColor = RGB(100, 0, 0); // red bg
txtColor = RGB(0, 100, 0); // green txt
txtHwnd = CreateWindow(L"Static", L"Hello World!", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 100, 100, 120, 30, hChild, (HMENU)testingTxtID, nullptr, nullptr);
SetWindowSubclass(txtHwnd, OwnerTxtProc, 0, 0);
break;
}
//...some other codes...
default:
return DefWindowProc(hChild, message, wParam, lParam);
}
return 0;
}
我在绘制静态文本控件时遇到问题。我已经阅读了一些有关此事的资料,也尝试了一些代码,但其中 none 行得通。我设法得到的最接近的是直到文本控件检测到我的鼠标悬停事件。为此,我使用控件子类化。但是,我不知道如何在鼠标悬停时绘制文本控件。
我的问题是:
我很困惑是把负责绘制文本控件的代码放在子类的
WM_MOUSEMOVE
还是WM_MOUSEHOVER
中。原因是因为在WM_MOUSEMOVE
中,我设置了当文本控件的矩形区域检测到光标时,应该进行绘制。同时,我觉得很奇怪,因为WM_MOUSEHOVER
不应该已经完成了那个特定角色吗?我真的需要有关如何在鼠标悬停时突出显示文本控件的帮助。
// global text control handler
HWND txtHwnd; //somewhere in the global area of codes
//class for mouse event tracking
class MouseTrackEvents
{
bool m_bMouseTracking;
public:
MouseTrackEvents() : m_bMouseTracking(false) {}
void OnMouseMove(HWND hwnd)
{
if (!m_bMouseTracking)
{
// Enable mouse tracking.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER;
tme.dwHoverTime = 100; //0.1s
TrackMouseEvent(&tme);
m_bMouseTracking = true;
}
}
void Reset(HWND hwnd)
{
m_bMouseTracking = false;
}
};
//subclass proc for text control
LRESULT CALLBACK OwnerTxtProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
//local mouse track object
MouseTrackEvents mouseTrack;
const int numOfMsg = 4;
int myMsgBox[numOfMsg]; //limit to only 4
HBRUSH hbrBkgndA = CreateSolidBrush(RGB(0, 255, 0));
//just want to print what wparam is..
int wmId, wmEvent;
wchar_t wParamHI[1000];
wchar_t wParamLO[1000];
//for painting
COLORREF hbrHighlight;
//HBRUSH hbrHighlight;
HDC txtHDC;
RECT txtRect;
POINT txtPt;
RECT txtRt;
switch (uMsg) {
case WM_CREATE: {
//testing purposes
myMsgBox[0] = MessageBox(nullptr, L"Yessir!", L":D", MB_OK | MB_ICONINFORMATION);
break;
}
case WM_MOUSEMOVE: {
mouseTrack.OnMouseMove(hWnd); //activate mouse tracking
GetWindowRect(hWnd, &txtRt); //see what value lies within
GetCursorPos(&txtPt);
if (PtInRect(&txtRt, txtPt)) {
//to check whether cursor is in text rect or not
MessageBox(nullptr, L"Okea..nice..!", L":D", MB_OK | MB_ICONINFORMATION);
//i dont know what to do here
//i was thinking that painting should be placed here...
//HBRUSH hbrBkgndEdit = CreateSolidBrush(RGB(100, 100, 255));
}
else {
//to check whether cursor is in text rect or not
MessageBox(nullptr, L"Oh noooo!", L":D", MB_OK | MB_ICONINFORMATION);
}
break;
}
case WM_MOUSEHOVER: {
//do something when txt ctrl is hovered
//to test whether wm_mousehover works, and the text control is mouse hovered
//myMsgBox[1] = MessageBox(nullptr, L"Yahooooo!", L":D", MB_OK | MB_ICONINFORMATION);
OutputDebugString(L"--------------This text control is being hovered---------------\n");
//testing painting when hovered
//plan is to send message to hChild to manage the painting since it is the parent window
//HDC theHDC = (HDC)wParam;
//SendMessage(hWnd, WM_CTLCOLORSTATIC, (WPARAM)theHDC, (LPARAM)txtHwnd);
//SendMessage(hWnd, WM_CTLCOLORSTATIC, (WPARAM)theHDC, lParam);
//for painting
//hbrHighlight = (COLORREF)(GetSysColor(COLOR_HIGHLIGHT));
//HDC hdcStatic = (HDC)wParam;
////SetTextColor(hdcStatic, RGB(0, 0, 0));
//SetBkColor(hdcStatic, hbrHighlight);
//for painting II
//HDC txtCtrlMe = (HDC)wParam;
//SetTextColor(txtCtrl, RGB(0, 0, 0));
//SetBkColor(txtCtrlMe, RGB(0, 255, 0));
//SendMessage(hChild, WM_CTLCOLORSTATIC, (WPARAM)txtCtrlMe, (LPARAM)txtHwnd);
//DeleteBrush(hbrBkgndA);
mouseTrack.Reset(hWnd);
//return (INT_PTR)hbrHighlight;
//mouseTrack.Reset(hWnd);
break;
//return TRUE;
}
//case WM_CTLCOLORSTATIC:
//{
// HDC txtCtrlMe = (HDC)wParam;
// //SetTextColor(txtCtrl, RGB(0, 0, 0));
// SetBkColor(txtCtrlMe, RGB(0, 255, 0));
// if (hbrBkgndA == NULL)
// {
// hbrBkgndA = CreateSolidBrush(RGB(255, 255, 255)); //eqivalent to delete brush objet
// }
// return (INT_PTR)hbrBkgndA;
// //break;
//}
//painting
/*
SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
SendMessage(hChild, WM_CTLCOLORSTATIC, (WPARAM)txtCtrlMe, (LPARAM)txtHwnd);
*/
//you can just ignore this, this is just for me to see whats inside wParam of the subclass
case WM_LBUTTONDOWN: {
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
int HI = swprintf_s(wParamHI, 1000, L"wParamHI: %d", wmEvent);
MessageBox(nullptr, wParamHI, L":D", MB_OK | MB_ICONINFORMATION);
int LO = swprintf_s(wParamLO, 1000, L"wParamLO: %d", wmId);
MessageBox(nullptr, wParamLO, L":D", MB_OK | MB_ICONINFORMATION);
break;
}
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
//child window proc, which contains the static text control
LRESULT CALLBACK WndProcChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
//...some other codes...
txtHwnd = CreateWindow(L"Static", L"Hello World!", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 100, 100, 120, 15, hChild, (HMENU)testingTxtID, nullptr, nullptr);
//control subclassing
//a.k.a attaching subclass proc to the static text control
SetWindowSubclass(txtHwnd, OwnerTxtProc, 0, 0);
//...some other codes...
default: {
return DefWindowProc(hChild, message, wParam, lParam);
}
return 0;
}
请忽略我在WM_MOUSEHOVER
和WM_CTLCOLORSTATIC
中注释掉的代码OwnerTxtProc(...)
。它们只是我用来尝试绘制文本控件的代码,但没有用。
您的控件的所有绘制操作都应该只在 WM_CTLCOLORSTATIC
处理程序内,甚至 WM_PAINT
处理程序内。
要触发控件的重绘,只需使用 InvalidateRect()
.
如果要更改绘制条件,请将相关信息存储在绘制代码使用的变量中,然后在使控件失效之前更新这些变量。
尝试这样的事情:
HWND txtHwnd;
bool bMouseTracking = false;
COLORREF bkgndColor = ...; // whatever you want...
COLORREF txtColor = ...; // whatever you want...
HBRUSH hbrBkgnd = nullptr;
const UINT APP_CTLCOLORSTATIC = WM_APP + 1;
LRESULT CALLBACK StaticTxtProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
switch (uMsg) {
case WM_NCDESTROY: {
RemoveWindowSubclass(hWnd, StaticTxtProc, uIdSubclass);
if (hbrBkgnd) {
DeleteBrush(hbrBkgnd);
hbrBkgnd = NULL;
}
bMouseTracking = false;
break;
}
case WM_MOUSEMOVE: {
if (!bMouseTracking) {
TRACKMOUSEEVENT tme = {};
tme.cbSize = sizeof(tme);
tme.hwndTrack = hWnd;
tme.dwFlags = TME_HOVER;
tme.dwHoverTime = 100; //0.1s
bMouseTracking = TrackMouseEvent(&tme);
}
RECT txtRt;
GetWindowRect(hWnd, &txtRt);
POINT txtPt;
GetCursorPos(&txtPt);
if (PtInRect(&txtRt, txtPt)) {
bkgndColor = ...; // whatever you want...
txtColor = ...; // whatever you want...
InvalidateRect(hWnd, NULL, TRUE);
}
break;
}
case WM_MOUSEHOVER: {
mMouseTracking = false;
bkgndColor = ...; // whatever you want...
txtColor = ...; // whatever you want...
InvalidateRect(hWnd, NULL, TRUE);
break;
}
case APP_CTLCOLORSTATIC: {
HDC hdc = reinterpret_cast<HDC>(wParam);
SetTextColor(hdc, txtColor);
SetBkColor(hdc, bkgndColor);
if (hbrBkgnd)
DeleteBrush(hbrBkgnd);
hbrBkgnd = CreateSolidBrush(bkgndColor);
return reinterpret_cast<LRESULT>(bkgndColor);
}
case WM_LBUTTONDOWN: {
// ...
break;
}
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK WndProcChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE: {
bkgndColor = ...; // whatever you want...
txtColor = ...; // whatever you want...
txtHwnd = CreateWindow(L"Static", L"Hello World!", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 100, 100, 120, 15, hChild, (HMENU)testingTxtID, nullptr, nullptr);
SetWindowSubclass(txtHwnd, StaticTxtProc, 0, 0);
break;
}
case WM_CTLCOLORSTATIC: {
return SendMessage(reinterpret_cast<HWND>(lParam), APP_CTLCOLORSTATIC, wParam, 0);
}
//...some other codes...
default: {
return DefWindowProc(hChild, message, wParam, lParam);
}
}
return 0;
}
(代答题者贴出答案移至答案space).
我设法解决了我在这件事上的问题。
//global variable(s)
COLORREF bkgndColor;
COLORREF txtColor;
HBRUSH hbrBkgnd = nullptr;
const UINT APP_CTLCOLORSTATIC = WM_APP + 1;
//class for mouse event
class MouseTrackEvents
{
bool m_bMouseTracking;
public:
MouseTrackEvents() : m_bMouseTracking(false) {}
void OnMouseMove(HWND hwnd)
{
if (!m_bMouseTracking)
{
// Enable mouse tracking.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = 10; //1ms
TrackMouseEvent(&tme);
m_bMouseTracking = true;
}
}
void Reset(HWND hwnd)
{
m_bMouseTracking = false;
}
};
//proc for static text contorl subclass
LRESULT CALLBACK OwnerTxtProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
//local mouse track variable
MouseTrackEvents mouseTrack;
RECT txtRt;
GetWindowRect(hWnd, &txtRt);
POINT txtPt;
GetCursorPos(&txtPt);
switch (uMsg) {
//...some other codes...
case WM_NCDESTROY: {
RemoveWindowSubclass(hWnd, OwnerTxtProc, uIdSubclass);
if (hbrBkgnd) {
DeleteBrush(hbrBkgnd);
hbrBkgnd = NULL;
}
mouseTrack.Reset(hWnd);
break;
}
case WM_MOUSEMOVE: {
mouseTrack.OnMouseMove(hWnd); //activate mouse tracking
break;
}
case WM_MOUSEHOVER: {
if (PtInRect(&txtRt, txtPt)) {
OutputDebugString(L"--------------This text control is being hovered---------------\n");
bkgndColor = RGB(0, 0, 200); // blue
txtColor = RGB(200, 0, 0); // red
InvalidateRect(hWnd, NULL, FALSE);
}
else {
OutputDebugString(L"--------------This text control is being left---------------\n");
bkgndColor = RGB(100, 0, 0); // red bg
txtColor = RGB(0, 100, 0); // green txt
InvalidateRect(hWnd, NULL, FALSE);
}
mouseTrack.Reset(hWnd);
break;
}
case WM_MOUSELEAVE: {
if (!(PtInRect(&txtRt, txtPt))) {
OutputDebugString(L"--------------This text control is being hovered---------------\n");
bkgndColor = RGB(100, 0, 0); // red bg
txtColor = RGB(0, 100, 0); // green txt
InvalidateRect(hWnd, NULL, FALSE);
}
mouseTrack.Reset(hWnd);
break;
}
case APP_CTLCOLORSTATIC: {
HDC hdc = reinterpret_cast<HDC>(wParam);
SetTextColor(hdc, txtColor);
SetBkColor(hdc, bkgndColor);
if (hbrBkgnd) {
DeleteBrush(hbrBkgnd);
}
hbrBkgnd = CreateSolidBrush(bkgndColor);
//return reinterpret_cast<LRESULT&>(bkgndColor); //--> error --> so i added '&'
return (LRESULT)hbrBkgnd;
}
//...some other codes...
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
//parent of static text control
LRESULT CALLBACK WndProcChild(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//...some other codes...
switch (message)
{
case WM_CTLCOLORSTATIC:
{
return SendMessage(reinterpret_cast<HWND>(lParam), APP_CTLCOLORSTATIC, wParam, 0);
}
case WM_CREATE: //put all sorts of stuff when the context menu is called
{
//font to be set to
hFont = CreateFont(17, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Segoe UI"));
//set font of the textCtrl
//doesnt work if handler target = hChild
for (int i = 0; i < textCtrlSize; i++) {
SendMessage(textCtrl[i], WM_SETFONT, (WPARAM)hFont, TRUE);
}
bkgndColor = RGB(100, 0, 0); // red bg
txtColor = RGB(0, 100, 0); // green txt
txtHwnd = CreateWindow(L"Static", L"Hello World!", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 100, 100, 120, 30, hChild, (HMENU)testingTxtID, nullptr, nullptr);
SetWindowSubclass(txtHwnd, OwnerTxtProc, 0, 0);
break;
}
//...some other codes...
default:
return DefWindowProc(hChild, message, wParam, lParam);
}
return 0;
}