15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Dialog box problem

Joern Dahl-Stamnes -- Jorn.Dahl-Stamnes@fysel.unit.no
Monday, August 05, 1996

Environment: NT3.51, VC++1.52

I have a problem with the OnKillfocus and the OnCancel functions in
a dialog box. Assume the following fields in a dialog box:

field       tab-order   functions
IDC_COUNT   1           OnKillfocus
IDC_VAL_1   2
IDC_VAL_2   3
IDOK        4           OnOK
IDCANCEL    5           OnCancel

When I enter the dialog box, IDC_COUNT has the focus. IDC_VAL_1 and
IDC_VAL_2 is both disabled. Depending on the value I enter in
IDC_COUNT, IDC_VAL_1 and/or IDC_VAL_2 will be enabled. When I use the
TAB key to leave the IDC_COUNT field, the OnKillfocus function read
the value in the IDC_COUNT field and then enable the IDC_VAL_1 and/or
the IDC_VAL_2 fields and then set focus the the first of the two fields.

The problem is that if I click on the Cancel button, the button is
pressed down but the OnCancle function never get called because the
OnKillfocus function do something that prevent OnCancel function to
get called.

I don't know how to solv this. Is there any way that I in the OnKillfocus
function can find out WHY IDC_COUNT lost focus? Other ideas how to fix
this? Thanks in advance.

-- 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Joern Yngve Dahl-Stamnes, Norwegian University of Science and Technology  |
| e-mail: Jorn.Dahl-Stamnes@fysel.unit.no                                   | 
| phone : +73 59 44 12, fax: +73 59 14 41                                   |
| Surfing the net? Try http://www.fysel.unit.no/dahls/dahls.html            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+



ppbillc@srv2.sj.ablecom.net
Wednesday, August 07, 1996

[Mini-digest: 8 responses]


> I don't know how to solv this. Is there any way that I in the OnKillfocus
> function can find out WHY IDC_COUNT lost focus? Other ideas how to fix
> this? Thanks in advance.

 Did  you call CDialog::OnKillFocus  in the OnKillFocus Function?

B

 /    \
 *    *
\ _,-._/
-----From: Vincent Mascart <100425.1337@CompuServe.COM>

>From: 	Joern Dahl-Stamnes
>Sent: 	mercredi 7 aout 1996 20:00
>To: 	INTERNET:MFC-L@NETCOM.COM
>Subject: 	Dialog box problem
>
>Environment: NT3.51, VC++1.52
>
>I have a problem with the OnKillfocus and the OnCancel functions in
>a dialog box. Assume the following fields in a dialog box:
>
>field       tab-order   functions
>IDC_COUNT   1           OnKillfocus
>IDC_VAL_1   2
>IDC_VAL_2   3
>IDOK        4           OnOK
>IDCANCEL    5           OnCancel
>
>When I enter the dialog box, IDC_COUNT has the focus. IDC_VAL_1 and
>IDC_VAL_2 is both disabled. Depending on the value I enter in
>IDC_COUNT, IDC_VAL_1 and/or IDC_VAL_2 will be enabled. When I use the
>TAB key to leave the IDC_COUNT field, the OnKillfocus function read
>the value in the IDC_COUNT field and then enable the IDC_VAL_1 and/or
>the IDC_VAL_2 fields and then set focus the the first of the two fields.
>
>The problem is that if I click on the Cancel button, the button is
>pressed down but the OnCancle function never get called because the
>OnKillfocus function do something that prevent OnCancel function to
>get called.
>
>I don't know how to solv this. Is there any way that I in the OnKillfocus
>function can find out WHY IDC_COUNT lost focus? Other ideas how to fix
>this? Thanks in advance.

On thing you did not say is what kind of control is IDC_COUNT.

If possible, you should check EN_CHANGED message from an edit controls,
CBN_CHANGE from a combobox, and so on instead of the kill focus message.

Another solution is to check the window which receive the focus like this:

if(GetFocus() != GetDlgItem(IDCANCEL))
{
	// normal behaviour of OnKillFocus
}

HTH

Vincent Mascart
100425.1337@compuserve.com

-----From: LeRoy Baxter 

This kind of stuff can get really ugly.  When you get a KillFocus, you need to determine
where the focus has been shifted to.  It can be done, but expect to put in a bunch of
hours to get it right.  You'd be better off to redesign so you don't have conditional
navigation within the dialog.  You can also get the value as it is typed in (and not
process the KillFocus).

-- 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Joern Yngve Dahl-Stamnes, Norwegian University of Science and Technology  |
| e-mail: Jorn.Dahl-Stamnes@fysel.unit.no                                   | 
| phone : +73 59 44 12, fax: +73 59 14 41                                   |
| Surfing the net? Try http://www.fysel.unit.no/dahls/dahls.html            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


-----From: David.Lowndes@bj.co.uk

It's always a bad idea to use the set/kill focus events to affect the focus and
enable/disable controls. In your situation it might be better to use the edit control's
change event (I assume IDC_COUNT is an edit control). Alternatively, use the kill
focus event to post yourself a user defined message, and do your enable/disable
logic there instead (so you delay your action).

Dave Lowndes
-----From: "Anthony DiBlasio" 

Whenever I need to do something immediately based on a value entered into an 
edit control (like enable other controls), I create a handler for the 
EN_CHANGE notification message.  You can enable your other controls 
immediately and allow the normal tabbing to occur.

Tony_DiBlasio@msn.com

-----From: Terry Trippany 

Hi,

At first I thought the behavior you describe is exactly what should happen. When you click on the 
cancel button while the focus is in IDC_COUNT a WM_KILLFOCUS notification message is sent to the 
parent window through WM_COMMAND (ie- an edit box would send EN_KILLFOCUS ...). When this happens 
the BN_CLICKED message never gets sent because it never really occurs in the Cancel button. The 
button will just get focus and is in fact never pushed down. If you click it again the OnCancel 
function is called appropriately. 

This is fine on the outside, but there does seem to be a problem with the message handling after the 
WM_KILLFOCUS is sent. If you look at the call stack you can see that you are in a DispatchMessage 
loop via CWnd::RunModalLoop. It appears that the first time you lose focus certain 
notification messages get lost somewhere. I couldn't recreate this with tabs, they worked fine. The 
mouse messages were disappearing for me. If you lost focus via a left mouse down then the next mouse 
down event seemed to disappear. This appears to be an MFC bug. 

Terry

*************************************
Terry Trippany
Senior Consultant
Strategic Technology Resources
343 West Erie Street, Suite 600
Chicago, IL  60610-4035

mailto:terryt@str.com
**************************************

Joern Dahl-Stamnes wrote:
> 
> Environment: NT3.51, VC++1.52
> 
> I have a problem with the OnKillfocus and the OnCancel functions in
> a dialog box. Assume the following fields in a dialog box:
> 
> field       tab-order   functions
> IDC_COUNT   1           OnKillfocus
> IDC_VAL_1   2
> IDC_VAL_2   3
> IDOK        4           OnOK
> IDCANCEL    5           OnCancel
> 
> When I enter the dialog box, IDC_COUNT has the focus. IDC_VAL_1 and
> IDC_VAL_2 is both disabled. Depending on the value I enter in
> IDC_COUNT, IDC_VAL_1 and/or IDC_VAL_2 will be enabled. When I use the
> TAB key to leave the IDC_COUNT field, the OnKillfocus function read
> the value in the IDC_COUNT field and then enable the IDC_VAL_1 and/or
> the IDC_VAL_2 fields and then set focus the the first of the two fields.
> 
> The problem is that if I click on the Cancel button, the button is
> pressed down but the OnCancle function never get called because the
> OnKillfocus function do something that prevent OnCancel function to
> get called.
> 
> I don't know how to solv this. Is there any way that I in the OnKillfocus
> function can find out WHY IDC_COUNT lost focus? Other ideas how to fix
> this? Thanks in advance.
> 
> --
> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> | Joern Yngve Dahl-Stamnes, Norwegian University of Science and Technology  |
> | e-mail: Jorn.Dahl-Stamnes@fysel.unit.no                                   |
> | phone : +73 59 44 12, fax: +73 59 14 41                                   |
> | Surfing the net? Try http://www.fysel.unit.no/dahls/dahls.html            |
> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-----From: Paramasivan Maddy 


The problem   here is,  focus is sent to  the Cancel button before the 
IDCANCEL notification is sent to the
dialog box, causing EN_KILLFOCUS to be generated by the control.

So to go around the problem, you can maintain a flag m_bDoValidation. And 
When the user clicks the
Cancel button, the dialog box is notified of the mouse-click by the child 
button through a   WM_PARENTNOTIFY
message. So in the OnParentNotify() method of the dialog box,   if the user 
clicked the cancel button then
m_bDoValidation can be set to FALSE. So this prevents the validation from 
taking place in the EN_KILLFOCUS
handler  and hence the focus is not set to IDC_VAL1 or IDC_VAL2.

Note:
    To ensure that the dialog receives the WM_PARENTNOTIFY message we
    have to explicitly remove the WS_EX_NOPARENTNOTIFY style from the
    Cancel button. For example:
   Or Uncheck the ParentNotify style for Cancel button in the AppStudio.
    BOOL CFocusTest::OnInitDialog()
    {
       CDialog::OnInitDialog();

       // Remove this style so we get the WM_PARENTNOTIFY when the
       // user clicks on the Cancel button
       GetDlgItem(IDCANCEL)->ModifyStyleEx(WS_EX_NOPARENTNOTIFY,0);
        // Rest of OnInitDialog
       ...
       ...
    }

The OnParentNotify method will look something like this:

void CFocusTest::OnParentNotify(UINT message, LPARAM lParam)
{
    CDialog::OnParentNotify(message, lParam);

    CPoint ptButtonDown(LOWORD(lParam), HIWORD(lParam)); // Mouse clicked on 
dialog.

    // Check if the cancel button is clicked!!
    if ((message == WM_LBUTTONDOWN) && (ChildWindowFromPoint(ptButtonDown) 
== GetDlgItem(IDCANCEL)))
        m_bDoValidation = FALSE;  // Trying to Cancel the dialog; don't 
validate.
}

//Ths kill focus function will look like this.
void CFocusTest::OnKillfocusCount()
{
     if (m_bDoValidation)
     {
          CString   csTest;
          m_Count.GetWindowText(csTest);
          if (csTest == "1")
          {
               m_Val1.EnableWindow(TRUE);
               m_Val1.SetFocus();
          }
          else
          {
               m_Val2.EnableWindow(TRUE);
               m_Val2.SetFocus();
          }
     }
          
}

Hope this helps you,
Maddy
-----From: "Todd Anderson" 

Did you try EN_CHANGE instead of OnKillFocus?  This gets sent if the
operator changed the data and after windows updates the display.  (I'm
assuming it's an edit control, I know a ListBox/Combobox also have a
similar message).  This should solve the focus problem.  I've never been
able to get this type of dialog to work with OnKillFocus, I always end up
using the change messages.


Todd




| Вернуться в корень Архива |