CRegionButton - 多向按钮






4.32/5 (20投票s)
2004 年 5 月 18 日
3分钟阅读

120994

1309
一个用于使按钮看起来好像具有多个区域的类。
引言
本文简要讨论了如何创建一个充当多向按钮的按钮类。大多数按钮在单击时执行一项任务。无论您单击按钮的哪个位置,任务仍然相同。如果任务恰好是在视口中沿某个方向(例如,向左)移动对象,则每个方向都需要一个按钮。可以做到,但有点笨拙。
一个小的改进可能是使用两个微调按钮控件,一个具有UDS_HORZ
样式,另一个具有UDS_VERT
样式。这两个控件可以放置在彼此的顶部,产生类似如下的效果:
虽然没有错误,但这种方法存在几个缺点。首先,控件不能完全重叠。很明显,一个控件实际上遮挡了另一个控件。这最多可能被认为是一个小小的烦恼。
其次,每个控件都需要自己的CSpinButtonCtrl
变量,这也意味着需要两个UDN_DELTAPOS
处理程序。这些处理程序可能如下所示:
void CRegionButtonTestDlg::OnDeltaposHorz(NMHDR* pNMHDR, LRESULT* pResult) { NM_UPDOWN *pNMUpDown = (NM_UPDOWN *) pNMHDR; if (0 < pNMUpDown->iDelta) ; // left else ; // right *pResult = 0; } void CRegionButtonTestDlg::OnDeltaposVert(NMHDR* pNMHDR, LRESULT* pResult) { NM_UPDOWN *pNMUpDown = (NM_UPDOWN *) pNMHDR; if (0 < pNMUpDown->iDelta) ; // down else ; // up *pResult = 0; }
如果您需要在一个处理程序中进行更改,那么您很可能也需要在另一个处理程序中进行更改。复制代码很少有趣。
一个更好的解决方案是使用一个控件,该控件根据单击的位置以不同的方式工作。按钮很好地满足了这种需求。
我创建的类CRegionButton
派生自CBitmapButton
,并且非常易于使用。它有两个私有成员变量和一个公共方法。这两个成员变量用于跟踪按钮上的不同区域。它目前适用于 4 个或 9 个区域,但只要它们是完美的正方形(例如 16、25),其他数字也可以使用。
公共方法CalculateRegions()
实际上是所有“魔法”发生的地方。它应该在LoadBitmaps()
之后调用。此方法将创建一个CRect
对象数组,表示位图的不同区域。
在 4 区域按钮的情况下,该按钮将被平均分为四个区域,编号为 0 到 3。
因此,如果用于按钮的位图为 80x80 像素,则按钮的区域 0 将为 l=0, t=0, r=39, 和 b=39。
计算出区域后,现在只需使用BN_CLICKED
处理程序检测鼠标点击即可。代码如下所示:
void CRegionButton::OnClicked() { CPoint pt; DWORD dwPos; // where was the mouse clicked dwPos = GetMessagePos(); // get the X/Y screen coordinates pt.x = LOWORD(dwPos); pt.y = HIWORD(dwPos); // convert them to client coordinates ScreenToClient(&pt); // see if the mouse click is within any of the regions for (UINT x = 0; x < m_uRegionCount; x++) { // if so, send a message to the parent // including the region that was clicked if (m_pRegion[x].PtInRect(pt) != FALSE) { GetParent()->SendMessage(UDM_REGION_CLICKED, x); break; } } }
发送到父级的消息是通过调用RegisterWindowMessage()
创建的已注册消息。您可以在该类的.h文件中看到此消息的实现。请注意,单击的区域作为WPARAM
参数发送。
至此,剩下的唯一事情就是响应消息。需要将ON_REGISTERED_MESSAGE()
条目添加到对话框的消息映射中。代码如下所示:
LRESULT CRegionButtonTestDlg::OnRegionClicked( WPARAM wParam, LPARAM lParam ) { CString str; str.Format("You clicked in region %u", wParam); return (0); }
现在,我们只有一个方法,无论我们单击按钮的哪个位置都会调用该方法,而且还会告诉我们在按钮上的哪个位置单击。使用时,此按钮可能如下所示:
尽情享用!