2011-11-04 89 views
0

我创建了两个Fred Acker's CHoverButtonEx类的实例,稍作修改以包含禁用状态。自定义控制图 - 焦点状态

这些按钮上包含以下属性模态对话框存在:

IDD_MY_DIALOG DIALOGEX 0, 0, 162, 27 
STYLE DS_SETFONT | WS_POPUP 
EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW 
FONT 9, "Arial", 400, 0, 0x0 
BEGIN 
    CONTROL   146,IDC_STATIC_BKGND,"Static",SS_BITMAP,0,0,162,27 
    LTEXT   "",IDC_STATIC_1,6,4,101,9,SS_WORDELLIPSIS 
    LTEXT   "",IDC_STATIC_2,6,15,101,9 
    CONTROL   "",IDC_BUTTON_1,"Button",BS_OWNERDRAW | WS_TABSTOP,108,4,24,19 
    CONTROL   "",IDC_BUTTON_2,"Button",BS_OWNERDRAW | WS_TABSTOP,134,4,24,19 
END 

一切都与不同之处在于按键运作良好,现在我需要实现聚焦状态,但行为很奇怪和意外。

在我DRAWITEM消息处理程序,我有以下的代码,其功能几乎完全一样的原始减去一些东西,我清理了这是没有必要:

void CHoverButtonEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{ 
// Do other stuff above and now find the state and draw the bitmap 

if(lpDrawItemStruct->itemState & ODS_SELECTED) 
{ 
    //mydc->BitBlt(0,0,m_ButtonSize.cx,m_ButtonSize.cy,pMemDC,m_ButtonSize.cx,0,SRCCOPY); 
    mydc->StretchBlt(0,0, lpDrawItemStruct->rcItem.right-lpDrawItemStruct->rcItem.left, 
     lpDrawItemStruct->rcItem.bottom-lpDrawItemStruct->rcItem.top, 
     pMemDC,m_ButtonSize.cx,0, m_ButtonSize.cx,m_ButtonSize.cy, SRCCOPY); 
} 
else 
{ 
    if(m_bHover) 
    { 
     //mydc->BitBlt(0,0,m_ButtonSize.cx,m_ButtonSize.cy,pMemDC,m_ButtonSize.cx*2,0,SRCCOPY); 
     mydc->StretchBlt(0,0, lpDrawItemStruct->rcItem.right-lpDrawItemStruct->rcItem.left, 
      lpDrawItemStruct->rcItem.bottom-lpDrawItemStruct->rcItem.top, 
      pMemDC,m_ButtonSize.cx*2,0, m_ButtonSize.cx,m_ButtonSize.cy, SRCCOPY); 
    } 
    else 
    { 
     if (IsWindowEnabled()) 
     { 
      //mydc->BitBlt(0,0,m_ButtonSize.cx,m_ButtonSize.cy,pMemDC,0,0,SRCCOPY); 
      mydc->StretchBlt(0,0, lpDrawItemStruct->rcItem.right-lpDrawItemStruct->rcItem.left, 
       lpDrawItemStruct->rcItem.bottom-lpDrawItemStruct->rcItem.top, 
       pMemDC,0,0, m_ButtonSize.cx,m_ButtonSize.cy, SRCCOPY); 
     } 
     else 
     { 
      //mydc->BitBlt(0,0,m_ButtonSize.cx,m_ButtonSize.cy,pMemDC,m_ButtonSize.cx*3,0,SRCCOPY); 
      mydc->StretchBlt(0,0, lpDrawItemStruct->rcItem.right-lpDrawItemStruct->rcItem.left, 
       lpDrawItemStruct->rcItem.bottom-lpDrawItemStruct->rcItem.top, 
       pMemDC,m_ButtonSize.cx*3,0, m_ButtonSize.cx,m_ButtonSize.cy, SRCCOPY); 
     } 
    } 
} 

if (lpDrawItemStruct->itemAction & ODA_FOCUS) 
{ 
    RECT rcFocus; 
    int iChange = 3; 
    rcFocus.top = lpDrawItemStruct->rcItem.top + iChange; 
    rcFocus.left = lpDrawItemStruct->rcItem.left + iChange; 
    rcFocus.right = lpDrawItemStruct->rcItem.right - iChange; 
    rcFocus.bottom = lpDrawItemStruct->rcItem.bottom - iChange; 
    pMemDC->DrawFocusRect(&rcFocus); 
} 

// clean up 
pMemDC -> SelectObject(pOldBitmap); 
delete pMemDC; 
} 

正在发生的事情是,当该对话框是活动窗口,我按一下标签,焦点框跳到第二个按钮,即使我可以通过按钮的点击处理程序确认第一个按钮具有真正的焦点。然后当我再次按下标签时,焦点框跳转到包括两个按钮。然后另一个标签按钮将焦点框移动到另一个按钮,最后另一个标签按钮完全移除焦点框。这个序列不断发生。即使按住Shift键也不会影响它。

我用spy ++嗅探了Windows消息,它看起来很正常。我得到了两个按钮控件的WM_DRAWITEM消息,并且它们被成功处理。

我会提到最后一件事;在我的对话框代码中,当我初始化按钮时,我不得不将按钮放置在z顺序的底部,否则IDC_STATIC_BKGND会画出按钮。这对我来说看起来并不正常,因为它们应该已经在z顺序的底部了。 (只要添加它,以防它是我的问题的一部分原因)。

m_button1.SetHorizontal(true); 
m_button1.SetMoveable(FALSE); 
m_button1.LoadBitmap(IDB_BUTTON_1); 
m_button1.SetToolTipText(_T("Some Text1")); 
// Draws the button after the background is drawn 
m_button1.SetWindowPos(&CWnd::wndBottom, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 

m_button2.SetHorizontal(true); 
m_button2.SetMoveable(FALSE); 
m_button2.LoadBitmap(IDB_BUTTON_2); 
m_button2.SetToolTipText(_T("Some Text2")); 
// Draws the button after the background is drawn 
m_button2.SetWindowPos(&CWnd::wndBottom, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 

有谁知道如何正确地为我的情况添加一个焦点框?

谢谢。

更新: 试图BrendanMcK的建议,并没有解决问题后,我挖了一些间谍++捕捉消息,发现的东西,似乎是古怪的行为。以下消息表示对话框中的单个选项卡按下。

<00283> 00870794 R WM_CTLCOLORBTN hBrush:01900015 
<00284> 00870794 S WM_DRAWITEM idCtl:112 lpdis:002AEF2C 
<00285> 00870794 R WM_DRAWITEM fProcessed:True 
<00286> 00870794 S DM_GETDEFID 
<00287> 00870794 R DM_GETDEFID wHasDef:DC_HASDEFID wDefID:0001 
<00288> 00870794 S WM_CTLCOLORBTN hdcButton:110114A7 hwndButton:01090502 
<00289> 00870794 R WM_CTLCOLORBTN hBrush:01900015 
<00290> 00870794 S WM_DRAWITEM idCtl:113 lpdis:002AF2A0 
<00291> 00870794 R WM_DRAWITEM fProcessed:True 

显然有两个单独的WM_DRAWITEM消息传递。每个消息的细节是:

消息#284:行动= ODA_FOCUS,状态= 0x0110(ODS_FOCUS = 0×0010)

消息#290:行动= ODA_DRAWENTIRE,状态= ODS_NOACCEL

我本来期望在消息#290中,该动作将再次成为ODA_FOCUS以允许另一个按钮“取消”对焦框。

我不确定为什么我使用Win7时甚至会收到ODS_NOACCEL状态。有什么我忘记禁用?

回答

0

MSDN on DRAWITEMSTATE

ODA_FOCUS 控制失去或得到键盘焦点。应检查itemState成员以确定控件是否具有焦点。

由于您正在重绘控件,因此如果itemState指示控件具有焦点,则应该只绘制焦点矩形。相反,你在所有情况下绘制它,关注是否控制收益或失去的重点。添加一个检查项目状态& ODS_FOCUS,你应该很好。

+0

感谢您的建议,但没有运气。我在主帖中添加了更新。 – sna14