Если я читаю вопрос правильно, ваша цель - получать уведомления, когда пользователь нажимает стандартную кнопку, тогда как стандартное поведение уведомлений для кнопок только отправляет WM_COMMANDs на «щелчки», где щелчок - это вся мышь вниз плюс мышь вверх последовательности.
Исторически для получения уведомлений BN_PUSHED и BN_UNPUSHED в вашем обработчике WM_COMMAND вы должны были использовать стиль окна BS_NOTIFY при создании кнопки. Однако, если вы прочитаете документацию для BN_PUSHED или BN_UNPUSHED, вы увидите
Этот код уведомления предоставляется только для совместимости с 16-разрядными версиями Windows, предшествующими версии 3.0. Приложения должны использовать стиль кнопки BS_OWNERDRAW и структуру DRAWITEMSTRUCT для этой задачи.
Это были очень старые уведомления, которые, насколько я могу судить, не просто устарели, но даже больше не поддерживаются. Вы можете, однако, сделать так, как предлагает документация: использовать кнопку, нарисованную владельцем, то есть кнопку, созданную в стиле BS_OWNERDRAW.
Это оказывается сложнее, чем просто создать кнопку с включенным BS_NOTIFY, поскольку кнопка больше не будет выполнять рисование по умолчанию сама по себе. Учитывая эту добавленную рутинную работу, я бы порекомендовал не делать этого таким образом, если только вы не хотите покрасить свои кнопки в любом случае - если только вам не понадобится нестандартный визуальный вид этих кнопок, а также нестандартное поведение уведомлений. В противном случае, я бы, вероятно, просто сделал бы подклассы Win32, поскольку кто-то другой предложил перехватить WM_LBUTTONDOWN и т. Д., А затем вызвать стандартную кнопку WNDPROC после выполнения некоторых действий над событиями, которые меня волновали.
В любом случае кнопка, нарисованная минимальным владельцем, которая сообщает о событиях кнопки вниз и кнопки вверх, выглядит следующим образом. (Я публикую события кнопки как пользовательские сообщения, но вы можете делать там все, что пожелаете)
#include <windows.h>
#define BTN_ID 101
#define WM_PUSHBUTTONDOWN WM_APP + 1
#define WM_PUSHBUTTONUP WM_APP + 2
HINSTANCE g_instance = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
g_instance = hInstance;
MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BACKGROUND);
wc.lpszClassName = L"owner_draw_btn";
if (!RegisterClass(&wc))
return -1;
if (!CreateWindow(wc.lpszClassName, L"foobar", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, 0, 0, hInstance, NULL))
return -1;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT HandleDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
auto* dis = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
if (dis->CtlType != ODT_BUTTON)
return 0;
auto style = (dis->itemState & ODS_SELECTED) ?
DFCS_BUTTONPUSH | DFCS_PUSHED :
DFCS_BUTTONPUSH;
auto rect = &dis->rcItem;
DrawFrameControl(dis->hDC, rect, DFC_BUTTON, style);
TCHAR text[512];
auto n = GetWindowText(dis->hwndItem, text, 512);
DrawText(dis->hDC, text, n, rect, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
if (dis->itemAction == ODA_SELECT) {
PostMessage(
hWnd,
(dis->itemState & ODS_SELECTED) ? WM_PUSHBUTTONDOWN : WM_PUSHBUTTONUP,
dis->CtlID,
0
);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
CreateWindow(
L"button", L"foobar",
BS_OWNERDRAW | WS_CHILD | WS_VISIBLE,
10, 10, 150, 35, hWnd,
(HMENU) BTN_ID,
g_instance,
0
);
return 0;
case WM_DRAWITEM:
return HandleDrawItem(hWnd, wParam, lParam);
case WM_PUSHBUTTONDOWN:
OutputDebugString(L"Button down event\n");
break;
case WM_PUSHBUTTONUP:
OutputDebugString(L"Button up event\n");
break;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}