#c #winapi #ownerdrawn
#c #winapi #ownerdrawn
Вопрос:
У меня есть кнопка, нарисованная владельцем, которую я хотел бы выделить, когда мышь наводится на нее. Вот упрощенный код, который, похоже, не работает:
case WM_DRAWITEM:
LPDRAWITEMSTRUCT pDraw = (LPDRAWITEMSTRUCT)lParam;
if(pDraw->itemState == ODS_HOTLIGHT) DrawButton(pDraw->hDC, HIcolor);
else DrawButton(pDraw->hDC, normcolor);
return 0;
DrawButton
это пользовательская функция, которая рисует кнопку. Вторым параметром этой функции является основной цвет кнопки. У функции нет проблем с отрисовкой кнопки. Проблема в обнаружении «состояния элемента».
Я также пробовал использовать if(pDraw->itemState amp; ODS_HOTLIGHT)
. Это тоже не работает.
Очевидно, я что-то упускаю. В своем поиске я наткнулся на множество ответов. Однако ни один из них не находится на C .
Комментарии:
1.
pDraw->itemState amp; ODS_HOTLIGHT
это единственно правильная проверка, а не==
. Постарайтесь убедиться, что вы действительно получили это сообщение о состоянии.
Ответ №1:
ODS_HOTLIGHT
Кнопка может не использоваться. Посмотрите, какие состояния возможны в структуре DRAWITEMSTRUCT?.
Вы можете использовать подклассы, а затем использовать TrackMouseEvent
для получения события SUBCLASSPROC
.
LRESULT CALLBACK Subclassproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
if (uMsg == WM_MOUSEMOVE)
{
TRACKMOUSEEVENT ev = {};
ev.cbSize = sizeof(TRACKMOUSEEVENT);
ev.dwFlags = TME_HOVER | TME_LEAVE;
ev.hwndTrack = hWnd;
ev.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(amp;ev);
}
else if (uMsg == WM_MOUSEHOVER)
{
RECT rc = {};
GetClientRect(hWnd, amp;rc);
HDC hdc = GetDC(hWnd);
SetDCBrushColor(hdc, RGB(255, 0, 0));
SelectObject(hdc, GetStockObject(DC_BRUSH));
RoundRect(hdc, rc.left, rc.top,
rc.right, rc.bottom, 0, 0);
}
else if (uMsg == WM_MOUSELEAVE)
{
RECT rc = {};
GetClientRect(hWnd, amp;rc);
HDC hdc = GetDC(hWnd);
SetDCBrushColor(hdc, RGB(0, 255, 0));
SelectObject(hdc, GetStockObject(DC_BRUSH));
RoundRect(hdc, rc.left, rc.top,
rc.right, rc.bottom, 0, 0);
TRACKMOUSEEVENT ev = {};
ev.cbSize = sizeof(TRACKMOUSEEVENT);
ev.dwFlags = TME_HOVER | TME_LEAVE | TME_CANCEL;
ev.hwndTrack = hWnd;
ev.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(amp;ev);
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
...
HWND hButton = CreateWindow(L"BUTTON", L"", WS_CHILD | WS_VISIBLE |
BS_OWNERDRAW, 10, 10, 60, 30, hWnd,
(HMENU)10001, hInst, NULL);
SetWindowSubclass(hButton, Subclassproc, 101, 0);
Комментарии:
1. Спасибо Дрейку Ву за этот очень информативный код и описание. У меня только один вопрос / уточнение. В
CreateWindow
этом случае вы присваиваете идентификатор «10001». Однако при настройке подкласса вы используете число «101». Это опечатка? Или это два разных числа?2. Это два разных значения. 10001 указывает
hMenu
, который можно использовать для получения уведомлений о кликах (WM_COMMAND=> wParam), а 101 указывает subclassid, который можно использовать для функции подкласса, напримерRemoveWindowSubclass
3. Спасибо. Я вижу разницу. В качестве альтернативного вопроса, можно ли использовать один и тот же номер в обоих случаях. Или это вызовет конфликт?
4. Нет. По крайней мере, образец, который я использовал, не противоречил друг другу. Эти два экземпляра представляют разные значения, и вы можете использовать одно и то же значение.
Ответ №2:
Как указано в описании ODS_HOTLIGHT
значения:
ODS_HOTLIGHT: элемент отслеживается по горячим следам, то есть элемент будет выделен, когда мышь находится на элементе.
Итак, я полагаю, что для получения этого сообщения вам нужно сначала использовать TrackMouseEvent
функцию.