About BS_DEFPUSHBUTTON and BS_PUSHBUTTON

Started by Jean-Pierre LEROY, June 30, 2005, 01:04:41 AM

Previous topic - Next topic

Jean-Pierre LEROY

Hi,

I've a test form with two button Command1 and Command2

In the Designer I just change the properties as below :

For Command1 : In WindowsStyle I check BS_DEFPUSHBUTTON
For Command2 : In WindowsStyle I check WS_DISABLE

Then when I click on the first button Command1 I would like :

1. To enabled the second button Command2.
2. To make the second button Command2 the default push button.

I have try this code without success; there is no problem to enabled the second button Command2; the problem is that when I hit the ENTER key, it is still the first button Command1 which is pressed even if I can see the a dark border around the second button Command2. ??? This second button Command2 should be "pressed" when the ENTER key is pressed because it is now the default push button.

Here is simple code :
'------------------------------------------------------------------------------------------------------------------------
Function MAINWINDOW_COMMAND1_BN_CLICKED ( _
                                       ControlIndex     As Long,  _  ' index in Control Array
                                       hWndForm         As Dword, _  ' handle of Form
                                       hWndControl      As Dword, _  ' handle of Control
                                       idButtonControl  As Long   _  ' identifier of button
                                       ) As Long
MsgBox("COMMAND1 CLICKED")

' Enabled COMMAND2
FF_Control_Enable(HWND_MAINWINDOW_COMMAND2)

' To change style of "COMMAND1" from %BS_DEFPUSHBUTTON to %BS_PUSHBUTTON
SendMessage HWND_MAINWINDOW_COMMAND1, %BM_SETSTYLE, %BS_PUSHBUTTON   , %TRUE

' To change style of "COMMAND2" from %BS_PUSHBUTTON to %BS_DEFPUSHBUTTON
SendMessage HWND_MAINWINDOW_COMMAND2, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE

End Function
                               

'------------------------------------------------------------------------------------------------------------------------
Function MAINWINDOW_COMMAND2_BN_CLICKED ( _
                                       ControlIndex     As Long,  _  ' index in Control Array
                                       hWndForm         As Dword, _  ' handle of Form
                                       hWndControl      As Dword, _  ' handle of Control
                                       idButtonControl  As Long   _  ' identifier of button
                                       ) As Long
MsgBox("COMMAND2 CLICKED")
End Function


Thank you for your help
Jean-Pierre LEROY

TechSupport

This is a harder problem because FireFly assigns the ID numbers for the different controls. You will need to manually re-define the Control ID for Command2 to be 1 and also reassign a new ID to Command1 so that both buttons do not have the same ID number.

You see, the default button on a Windows dialog is assigned the value of 1. Simply re-defining the button to %BS_DEFPUSHBUTTON does not re-assign the ID number.

Maybe try something like the following in your Clicked message handler;

IDC_MAINWINDOW_COMMAND1 = IDC_MAINWINDOW_COMMAND2
IDC_MAINWINDOW_COMMAND2 = 1


There is also issues with the black border of Command buttons changing to other Command buttons as you Tab through the controls on your Form. This appears to be standard Windows behaviour although it does look counter-intuitive. I remember Roger Garstang having a topic on the PB Forum about this wierd behaviour.

Jean-Pierre LEROY

Hi Paul,

I've tried to change the control ID without success.

After more tests I think that the problem is :

If I add a FF_Control_SetFocus(HWND_MAINWINDOW_COMMAND2) in the MAINWINDOW_COMMAND1_BN_CLICKED function then the second button Command2 became the default push button (this what I want); but as soon as I change the focus by program on another control I lost the the default push button; the default push button sould be pressed when the ENTER key is pressed even if the focus is not on that button.

I think that the problem is here.

Jean-Pierre

Jean-Pierre LEROY

I've found these information on Internet about "Changing/Setting the Default Push Button in a Dialog Box"?
 
1. Send the BM_SETSTYLE message to the current default push button to change its border to that of a regular push button :
SendMessage HWND_MAINWINDOW_COMMAND1, %BM_SETSTYLE, %BS_PUSHBUTTON   , %TRUE
 
2. Send a DM_SETDEFID message to the dialog box to change the ID of the default push button:

=> How can I do that within FireFly ?
 
3. Send the BM_SETSTYLE message to the new default push button to change its border to that of a default push button :

SendMessage HWND_MAINWINDOW_COMMAND2, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE

Thank you for your help.
Jean-Pierre.

Edwin Knoppert2

If a control's ID is an issue you can reset this via SetWindowLong() + GWL_ID :)

Roger Garstang

Oh yeah, the wonderful Button issues.  I still to this day think Windows changed and I didn't notice it.  What is the point of a default button if it is only default while in a Textbox.  To me Enter has always been the Default Button and Spacebar is the current focused (dotted) button, but somehow it changed on me and I didn't notice.  There are all kinds of issues when you change these dynamically.  When you disable Default or Cancel buttons you have even more problems.  Black Borders stay on disabled buttons, multiple buttons get Black Borders, the app sometimes beeps and other weird things when Cancel buttons are disabled, and many other annoying things.  The Find Next button in PB's Find still isn't fixed and shows a Border on a disabled button.

BM_SETSTYLE and DM_SETDEFID are the proper ways to adjust the behavior and display, and to get the Ok/Cancel Effects like Enter and Esc reactions you need to set the IDs.

TechSupport

I have taken a look at this issue a little further. Edwin is right that we also need to change the button's ID via SetWindowLong. Also, FireFly had hardcoded the default command button's ID in the FireFly generated source code for the %DM_GETDLGID message (e.g. %IDC_FORM1_COMMAND1). I have modified the FireFly EXE to fix this "problem". I will upload the new EXE later today in addition to the code needed in FireFly to change the default button (mostly similar to the code that has already been posted in this thread).

TechSupport

Hi Jean-Pierre,

I just emailed you the new FireFly exe with the fix. I would use following code to change your default button.


Function FORM1_COMMAND1_BN_CLICKED ( _
                                  ControlIndex     As Long,  _  ' index in Control Array
                                  hWndForm         As Dword, _  ' handle of Form
                                  hWndControl      As Dword, _  ' handle of Control
                                  idButtonControl  As Long   _  ' identifier of button
                                  ) As Long

FF_Control_Enable HWND_FORM1_COMMAND2


're-assign the ID's so that COMMAND2 now has the default ID (%IDOK = 1)
SetWindowLong HWND_FORM1_COMMAND1, %GWL_ID, IDC_FORM1_COMMAND2
SetWindowLong HWND_FORM1_COMMAND2, %GWL_ID, 1   '%IDOK

're-assign the internal FireFly variables
IDC_FORM1_COMMAND1 = IDC_FORM1_COMMAND2
IDC_FORM1_COMMAND2 = 1

'Change the styles of the buttons
SendMessage HWND_FORM1_COMMAND1, %BM_SETSTYLE, %BS_PUSHBUTTON, %TRUE
SendMessage HWND_FORM1_COMMAND2, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE

End Function


To be honest, I don't know why you would change the default button once it has been set. I would think that this would confuse the user because he would not know which button to expect to be the default at any given time (unless one is active and the other is disabled).

Jean-Pierre LEROY

Hi Paul,

Thank you for the fix.

"To be honest, I don't know why you would change the default button once it has been set. I would think that this would confuse the user because he would not know which button to expect to be the default at any given time (unless one is active and the other is disabled)."

=> I've made an application for users that can't use the mouse or prefer to use the keyboard; in a form I've two buttons "Search" and "View"; at first the "Search" button have to be the "default button"; then if the search give one or more results, the "View" button is enabled and became the default button.

So far I've made some tests with the new engine; when I click on the first button button1, the second button button2 became the defaut button, no problem; then I've just added a FORM1_COMMAND2_BN_CLICKED to return to the initial state without any succes; the second button remains the default button; here is the complete code i've used :


'------------------------------------------------------------------------------------------------------------------------
Function FORM1_COMMAND1_BN_CLICKED ( _
                                  ControlIndex     As Long,  _  ' index in Control Array
                                  hWndForm         As Dword, _  ' handle of Form
                                  hWndControl      As Dword, _  ' handle of Control
                                  idButtonControl  As Long   _  ' identifier of button
                                  ) As Long                                  

MsgBox("COMMAND1 Clicked")

' Enabled COMMAND2
FF_Control_Enable(HWND_FORM1_COMMAND2)

're-assign the ID's so that COMMAND2 now has the default ID (%IDOK = 1)
SetWindowLong HWND_FORM1_COMMAND1, %GWL_ID, IDC_FORM1_COMMAND2
SetWindowLong HWND_FORM1_COMMAND2, %GWL_ID, 1   '%IDOK

're-assign the internal FireFly variables
IDC_FORM1_COMMAND1 = IDC_FORM1_COMMAND2
IDC_FORM1_COMMAND2 = 1

'Change the styles of the buttons
SendMessage HWND_FORM1_COMMAND1, %BM_SETSTYLE, %BS_PUSHBUTTON, %TRUE
SendMessage HWND_FORM1_COMMAND2, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE
     
End Function

'------------------------------------------------------------------------------------------------------------------------
Function FORM1_COMMAND2_BN_CLICKED ( _
                                  ControlIndex     As Long,  _  ' index in Control Array
                                  hWndForm         As Dword, _  ' handle of Form
                                  hWndControl      As Dword, _  ' handle of Control
                                  idButtonControl  As Long   _  ' identifier of button
                                  ) As Long
   
   MsgBox("COMMAND2 Clicked")
                                     
're-assign the ID's so that COMMAND1 now has the default ID (%IDOK = 1)
SetWindowLong HWND_FORM1_COMMAND2, %GWL_ID, IDC_FORM1_COMMAND1
SetWindowLong HWND_FORM1_COMMAND1, %GWL_ID, 1   '%IDOK

're-assign the internal FireFly variables
IDC_FORM1_COMMAND2 = IDC_FORM1_COMMAND1
IDC_FORM1_COMMAND1 = 1

   'Change the styles of the buttons
SendMessage HWND_FORM1_COMMAND2, %BM_SETSTYLE, %BS_PUSHBUTTON, %TRUE
SendMessage HWND_FORM1_COMMAND1, %BM_SETSTYLE, %BS_DEFPUSHBUTTON, %TRUE

End Function


Jean-Pierre

TechSupport

Hi Jean-Pierre,

I will check into this tomorrow. Seems like a tough problem but we're getting closer to making it work.

TechSupport

Hi Jean-Pierre,

A strange thing happens when you click on Button1. Basically, the changing of the default button style causes the Click event for Button2 to fire. Of course when that fires, your code that reverts the default button back to Button1 will execute.

I tried adding a global flag that seems to work. At the top of your Form place this code:

Global gClickFlag As Long


In your Click event for Button1, place this at the end:

gClickFlag = %TRUE


In the code for the Click event for Button2, place the following at the beginning:

If gClickFlag Then
  gClickFlag = %FALSE
  Exit Function
End If


Please let me know if this works for you.

Jean-Pierre LEROY

Hi Paul,

Thank you for help; it's not an easy way to change the default button and it doesn't works all the time with the global flag.

Can you tell me why sending a DM_SETDEFID message to the dialog box to change the ID of the default push button could not be an issue to this problem ?

Jean-Pierre