SetFocus for button controls
Roger Onslow -- Roger_Onslow@compsys.com.au Thursday, August 22, 1996 Environment: VC 4.1 Windows 95 I have a number of controls of various types on my dialog (property page actually) and I need to perform certain actions when each control receives focus. I use WM_SETFOCUS handlers for my controls, and this works just fine for edit controls. However, this message is NOT sent when a button control (push button, checkbox or radio button) gets focus. Obviously, buttons *do* receive focus (as buttons get grayed focus rect draw around them etc), and I know from implementing owner drawn buttons in the past, that one has to handle the drawing of the button when it has focus (ie. draw one's own focus rect). However, the only message a button seems to handle is the click (or double click if owner drawn). I can't seem to find any message that is sent when a button gets focus. How *can* I find out when a given button gets the focus? Thanks in advance Roger Onslow Senior Software Engineer Computer Systems Australia RogerO@compsys.com.au
John Simmons -- jms@connectnet.com Sunday, August 25, 1996 [Mini-digest: 3 responses] At 03:05 PM 8/22/96 EAT, you wrote: >Environment: VC 4.1 Windows 95 > >I have a number of controls of various types on my dialog >(property page actually) and I need to perform certain >actions when each control receives focus. > >I use WM_SETFOCUS handlers for my controls, and this works >just fine for edit controls. However, this message is NOT >sent when a button control (push button, checkbox or radio >button) gets focus. > >Obviously, buttons *do* receive focus (as buttons get >grayed focus rect draw around them etc), and I know from >implementing owner drawn buttons in the past, that one >has to handle the drawing of the button when it has focus >(ie. draw one's own focus rect). However, the only >message a button seems to handle is the click (or double >click if owner drawn). I can't seem to find any message >that is sent when a button gets focus. > >How *can* I find out when a given button gets the focus? For buttons (checkboxes, radio buttons & pushbuttons) , you have to check for ON_BN_CLICKED. However, the dialog box still doesn't know what control has the focus if the user tabs to a button or uses the up/down arrow keys in a radio button group. I've attached a file that shows how to get around this problem. It's called KEYSNAG.TXT. If you have any questions gimme a shout. struct vpCtlInfo { UINT Id; BOOL AcceptsCalc; BOOL IsCurrency; double MinValue; double MaxValue; }; const UINT KEY_HELP = 1000, KEY_PGUP = 1001, KEY_PGDN = 1002, KEY_TAB = 1003; class CMyDlg : public CDialog { // holds control info for Calculator call vpCtlInfo m_CurrentCtl; // for trapping F1 key to show proper help // FARPROC lpfnFilterProc; static HHOOK HookID; HINSTANCE hInst; #ifdef WIN32 static DWORD CALLBACK KeystrokeHook(int nCode, WORD wParam, LONG lParam); #else static DWORD __export CALLBACK KeystrokeHook(int nCode, WORD wParam, LONG lParam); #endif void GetFocusedControl(); public: CmyDlg(CWnd* pParent = NULL); //{{AFX_DATA(CGrowthAdmin) enum { IDD = DLG_MyDlg }; //}}AFX_DATA protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //{{AFX_MSG(CMyDlg) afx_msg void OnOKAY(); afx_msg void OnCANCEL(); afx_msg LONG OnKeystroke(UINT, LONG); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; /////////////////////////////////////////////////////////////// // CMyDlg dialog BEGIN_MESSAGE_MAP(CMyDlg, CDialog) //{{AFX_MSG_MAP(CMyDlg) ON_COMMAND(IDOK,OnOKAY) ON_COMMAND(IDCANCEL,OnCANCEL) ON_COMMAND(VPHELP,OnVPHELP) ON_COMMAND(VPNEXT,OnVPNEXT) ON_COMMAND(VPPREV,OnVPPREV) ON_MESSAGE(WM_KEYSTROKE,OnKeystroke) //}}AFX_MSG_MAP END_MESSAGE_MAP() //--------------------------------------------------------------/ CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) :CDialog(CMyDlg::IDD, pParent) { //{{AFX_DATA_INIT(CMyDlg) //}}AFX_DATA_INIT } //--------------------------------------------------------------/ void CMyDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMyDlg) //}}AFX_DATA_MAP } HHOOK CMyDlg::HookID=0; //--------------------------------------------------------------/ BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); LPDWORD processid = 0; #ifdef WIN32 HookID = SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)CMyDlg::KeystrokeHook, theApp.m_hInstance, GetWindowThreadProcessId(m_hWnd, processid)); #else HookID = SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)CMyDlg::KeystrokeHook, theApp.m_hInstance, GetWindowTask(m_hWnd)); #endif return TRUE; // return TRUE unless you set the focus to a control } //------------------------------------------------------------/ void CMyDlg::OnOKAY() { #ifdef WIN32 UnhookWindowsHookEx(CMyDlg::HookID); #else UnhookWindowsHook(WH_MSGFILTER, (HOOKPROC)CLifeInsDetail::KeystrokeHook); #endif EndDialog(IDOK); } //------------------------------------------------------------/ void CMyDlg::OnCANCEL() { #ifdef WIN32 UnhookWindowsHookEx(CMyDlg::HookID); #else UnhookWindowsHook(WH_MSGFILTER, (HOOKPROC)CLifeInsDetail::KeystrokeHook); #endif EndDialog(IDCANCEL); } //------------------------------------------------------------/ void CMyDlg::OnVPHELP() { WinHelp(IDD, HELP_CONTEXT); GotoDlgCtrl(GetDlgItem(m_CurrentCtl.Id)); } //------------------------------------------------------------/ void CMyDlg::OnVPNEXT() { #ifdef WIN32 UnhookWindowsHookEx(CMyDlg::HookID); #else UnhookWindowsHook(WH_MSGFILTER, (HOOKPROC)CLifeInsDetail::KeystrokeHook); #endif EndDialog(VPNEXT); } //-----------------------------------------------------------/ void CMyDlg::OnVPPREV() { #ifdef WIN32 UnhookWindowsHookEx(CMyDlg::HookID); #else UnhookWindowsHook(WH_MSGFILTER,(HOOKPROC) CLifeInsDetail::KeystrokeHook); #endif EndDialog(VPPREV); } //-----------------------------------------------------------// LONG CMyDlg::OnKeystroke(UINT wParam, LONG lParam) { switch (toupper(wParam)) { case KEY_HELP : OnVPHELP(); return 1L; case KEY_PGDN : OnVPNEXT(); return 1L; case KEY_PGUP : OnVPPREV(); return 1L; case KEY_TAB : GetFocusedControl(); return 0L; default : break; } return 1L; } //------------------------------------------------------------// /* This function catches arrowkey movement and tab/shift-tab key strokes. The reason is that we had to know if the currently focused control was a button. As long as the user clicks on the button with the mouse, everything is cool, but the minute they use a keystroke to move between controls, the dialog doesn't know which control has the focus (if it's a button). This was more efficient than enumerating thru the list of controls to see which one had the focus. */ //------------------------------------------------------------// void CMyDlg::GetFocusedControl() { m_CurrentCtl.Id = GetFocus()->GetDlgCtrlID(); char classname[80]; CString ClassName; ClassName.Empty(); if (::GetClassName(GetDlgItem(m_CurrentCtl.Id)->m_hWnd, classname, sizeof(classname))) ClassName = classname; if (ClassName.Find("Button") >= 0) m_CurrentCtl.AcceptsCalc = FALSE; } //-----------------------------------------------------------// #ifdef WIN32 DWORD CALLBACK CMyDlg::KeystrokeHook(int nCode, WORD wParam, LONG lParam) #else DWORD __export CALLBACK CLifeInsDetail::KeystrokeHook(int nCode, WORD wParam, LONG lParam) #endif { if (nCode < 0) return CallNextHookEx((HHOOK) HookID, nCode, wParam, lParam); if (nCode == MSGF_DIALOGBOX) { MSG FAR *ptrMsg = (MSG FAR *)lParam; if (WM_KEYDOWN == ptrMsg->message) { switch (ptrMsg->wParam) { case VK_F1 : ::PostMessage(::GetParent(ptrMsg->hwnd),WM_KEYSTROKE,KEY_HELP,lParam); return 1L; case VK_NEXT : ::PostMessage(::GetParent(ptrMsg->hwnd),WM_KEYSTROKE,KEY_PGDN,lParam); return 1L; case VK_PRIOR : ::PostMessage(::GetParent(ptrMsg->hwnd),WM_KEYSTROKE,KEY_PGUP,lParam); return 1L; case VK_UP : case VK_DOWN : case VK_RIGHT : case VK_LEFT : case VK_TAB : ::PostMessage(::GetParent(ptrMsg->hwnd),WM_KEYSTROKE,KEY_TAB,lParam); return 0L; } } } return 0L; } /=========================================================\ | John Simmons (Redneck Techno-Biker) | | jms@connectnet.com | | Home Page | | www2.connectnet.com/users/jms/ | |---------------------------------------------------------| | ViewPlan, Inc. home page (my employer) | | www.viewplan.com/index.html | |---------------------------------------------------------| | IGN #12 American Eagle Motorsports Zerex Ford | | Teammates - Steve Stevens (#13 Hooters Ford and | | 1995 IGN Points Champ) | | Pat Campbell (#14 Dr. Pepper Ford) | | American Eagle Motorsports Team Page | | www2.connectnet.com/users/jms/ignteam | | Hawaii Multi-Player Nickname: AEMwest | |---------------------------------------------------------| | Competitor - Longest Signature File On The Net | \=========================================================/ -----From: "S. Balachandar"Hi There is a notification message for button controls which they will send = to the parent whenever they receive focus. It is similar to EN_SETFOCUS = of the edit control.. The message is BN_SETFOCUS. But to get this notification message the = button control should have the BS_NOTIFY style set. [Note : = Notifications are sent thru WM_COMMAND message to the parent ]. Hope this helps Bala -------------------------------------------------------------------------= ---------------------------------------- S. Balachandar e-mail : = chandar@adca01.enet.dec.com Software Engineer Phone : 3370445 Ext : 479 Digital Equipment (I) Ltd., Fax : 3371498 Digital House, 45/14 Tumkur Road, =20 Yeshwanthpur II Stage, =20 Bangalore 560 022. =20 -------------------------------------------------------------------------= ---------------------------------------- -----From: "Greg Tighe" A button sends the BN_DISABLE, BN_PUSHED, BN_KILLFOCUS, BN_PAINT, BN_SETFOCUS, and BN_UNPUSHED notification messages only if it has the BS_NOTIFY style. It sends the BN_CLICKED and BN_DBLCLK notification messages regardless of the BS_NOTIFY style. -Greg Tighe Applied Intelligent Systems, Inc. Ann Arbor, MI gdt@aisinc.com
Gabriel Parlea-Visalon -- Gabriel@derivs.demon.co.uk Tuesday, August 27, 1996 In your message dated Thursday 22, August 1996 you wrote : > Environment: VC 4.1 Windows 95 > > I have a number of controls of various types on my dialog (property page > actually) > and I need to perform certain actions when each control receives focus. > > I use WM_SETFOCUS handlers for my controls, and this works just fine for edit > controls. > > However, this message is NOT sent when a button control (push button, checkbox > or radio button) > gets focus. > > Obviously, buttons *do* receive focus (as buttons get grayed focus rect draw > around > them etc), and I know from implementing owner drawn buttons in the past, that > one has > to handle the drawing of the button when it has focus (ie. draw one's own focus > rect). > However, the only message a button seems to handle is the click (or double > click if > owner drawn). I can't seem to find any message that is sent when a button gets > focus. > > How *can* I find out when a given button gets the focus? > > Thanks in advance > > Roger Onslow > Senior Software Engineer > Computer Systems Australia > RogerO@compsys.com.au > Override OnKillFocus() for the CPropertySheet and check for the button pointer. Gabriel -- Gabriel Parlea-Visalon Software Engineer Derivative Trading Systems gabriel@derivs.demon.co.uk
| Вернуться в корень Архива |