子类按钮不会在每次重复点击时产生动画
Subclassed button not producing animation on every repeated click
我在 WindowProc
回调的 WM_CREATE
消息中创建了一个自定义子 classed 按钮。下面是创建和 subclassing 指令,以及用于控制按钮状态的结构:
static button_state btnstateBtnInstall;
hBtnInstall = CreateWindow(WC_BUTTON, L"Button", WS_CHILD | WS_VISIBLE, (window_width / 2) - (btn_install_width / 2), window_height - (window_height / 6) - (btn_install_height / 2), btn_install_width, btn_install_height, hwnd, (HMENU)HMENU_btn_install, NULL, NULL);
SetWindowSubclass(hBtnInstall, BtnInstallProc, 0, (DWORD_PTR)&btnstateBtnInstall);
结构定义如下:
struct button_state
{
bool pushed;
button_state() { pushed = false; }
};
subclassed过程编码如下:
LRESULT CALLBACK BtnInstallProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubClass, DWORD_PTR dwRefData)
{
button_state* state = (button_state*)dwRefData;
// Omitted part where I create brushes and font to be used for painting
switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc = ps.rcPaint;
POINT pt;
GetCursorPos(&pt);
ScreenToClient(hwnd, &pt);
BOOL hover = PtInRect(&rc, pt);
if (state->pushed)
{
// Pushed
FillRect(hdc, &rc, hBrPushed);
}
else if (hover)
{
// Mouse over
FillRect(hdc, &rc, hBrHover);
}
else
{
// Normal
FillRect(hdc, &rc, hBrNormal);
}
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(255, 255, 255));
SelectFont(hdc, SegoeUI);
static LPCWSTR InstallBtnTxt = L"Install";
static int InstallBtnTxtLen = static_cast<int>(wcslen(InstallBtnTxt)); // Should be a safe cast, for small arrays like this one
DrawText(hdc, InstallBtnTxt, InstallBtnTxtLen, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
}
case WM_LBUTTONDOWN:
{
state->pushed = true;
break;
}
case WM_LBUTTONUP:
{
state->pushed = false;
break;
}
// Omitted part where I handle WM_DESTROY to do cleanup
}
return DefSubclassProc(hwnd, msg, wParam, lParam);
}
为了将我的按钮的行为与标准按钮的行为进行比较,我创建了另一个没有子classing 并且仅使用标准 BUTTON
class 和 WS_VISIBLE | WS_CHILD
的按钮属性。
正如您从附加的 gif 中看到的那样,当我 重复单击标准 class 按钮时,每次单击都会产生动画 而当多次单击时 我用这段代码创建的按钮似乎并没有捕捉到每一次点击,但(如您所见)大约有 50%。
我错过了什么?为什么我的按钮不像标准按钮那样灵敏 class?
TL;DR: 当慢慢点击我的子classed 按钮时,绘画是正确的。正如您从我的附图中看到的那样,重复点击它们时,我的按钮和标准按钮之间的区别很大。我怎样才能让我的控件像标准控件一样响应迅速?
当您快速点击时,某些 WM_LBUTTONDOWN
消息会被 WM_LBUTTONDBLCLK
取代(默认双击处理)。您需要像处理 WM_LBUTTONDOWN
消息一样处理它。
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK: // <-- Added
{
state->pushed = true;
break;
}
我在 WindowProc
回调的 WM_CREATE
消息中创建了一个自定义子 classed 按钮。下面是创建和 subclassing 指令,以及用于控制按钮状态的结构:
static button_state btnstateBtnInstall;
hBtnInstall = CreateWindow(WC_BUTTON, L"Button", WS_CHILD | WS_VISIBLE, (window_width / 2) - (btn_install_width / 2), window_height - (window_height / 6) - (btn_install_height / 2), btn_install_width, btn_install_height, hwnd, (HMENU)HMENU_btn_install, NULL, NULL);
SetWindowSubclass(hBtnInstall, BtnInstallProc, 0, (DWORD_PTR)&btnstateBtnInstall);
结构定义如下:
struct button_state
{
bool pushed;
button_state() { pushed = false; }
};
subclassed过程编码如下:
LRESULT CALLBACK BtnInstallProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubClass, DWORD_PTR dwRefData)
{
button_state* state = (button_state*)dwRefData;
// Omitted part where I create brushes and font to be used for painting
switch (msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc = ps.rcPaint;
POINT pt;
GetCursorPos(&pt);
ScreenToClient(hwnd, &pt);
BOOL hover = PtInRect(&rc, pt);
if (state->pushed)
{
// Pushed
FillRect(hdc, &rc, hBrPushed);
}
else if (hover)
{
// Mouse over
FillRect(hdc, &rc, hBrHover);
}
else
{
// Normal
FillRect(hdc, &rc, hBrNormal);
}
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(255, 255, 255));
SelectFont(hdc, SegoeUI);
static LPCWSTR InstallBtnTxt = L"Install";
static int InstallBtnTxtLen = static_cast<int>(wcslen(InstallBtnTxt)); // Should be a safe cast, for small arrays like this one
DrawText(hdc, InstallBtnTxt, InstallBtnTxtLen, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
}
case WM_LBUTTONDOWN:
{
state->pushed = true;
break;
}
case WM_LBUTTONUP:
{
state->pushed = false;
break;
}
// Omitted part where I handle WM_DESTROY to do cleanup
}
return DefSubclassProc(hwnd, msg, wParam, lParam);
}
为了将我的按钮的行为与标准按钮的行为进行比较,我创建了另一个没有子classing 并且仅使用标准 BUTTON
class 和 WS_VISIBLE | WS_CHILD
的按钮属性。
正如您从附加的 gif 中看到的那样,当我 重复单击标准 class 按钮时,每次单击都会产生动画 而当多次单击时 我用这段代码创建的按钮似乎并没有捕捉到每一次点击,但(如您所见)大约有 50%。
我错过了什么?为什么我的按钮不像标准按钮那样灵敏 class?
TL;DR: 当慢慢点击我的子classed 按钮时,绘画是正确的。正如您从我的附图中看到的那样,重复点击它们时,我的按钮和标准按钮之间的区别很大。我怎样才能让我的控件像标准控件一样响应迅速?
当您快速点击时,某些 WM_LBUTTONDOWN
消息会被 WM_LBUTTONDBLCLK
取代(默认双击处理)。您需要像处理 WM_LBUTTONDOWN
消息一样处理它。
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK: // <-- Added
{
state->pushed = true;
break;
}