SetFocus.. Where am I going wrong

Started by Martin Francom, March 17, 2010, 07:55:33 PM

Previous topic - Next topic

Cho Sing Kum

#15
Hi Rolf,

You did a very good test.

In VB6, the Hello-Button is on top of the tab order (TabIndex 0). Therefore, at startup, it has the input focus and therefore must be the default button (as in tab to it, per MSDN documentation). The OK button therefore has to lose its default status at startup.

MSDN
http://msdn.microsoft.com/en-us/library/aa511453.aspx
QUOTE
The default command button is invoked when users press the Enter key. It is assigned by the developer, but any command button becomes the default when users tab to it.
.
.
Any command button becomes the default when users tab to it. If the input focus is on a control that isn't a command button, the command button with the default button attribute becomes the default. Only one command button in a window can be the default.
UNQUOTE

In this case, although the user do not physically need tab to it (Hello-Button) but it is still consider to have been so since TabIndex = 0.

Your examples make this so much clearer.

Edited to add:
The PBForms version behave like FF, not VB6. I tested earlier today on PBForms 2.01. I think because underneath, both FF and PBForms use PB.

Rolf Brandt

I think the test program would have been better it we would have another control on it like a text box to see how the program behaves. I tried it also with PwrDef and EZGui DDT. I noticed all act a little different which has mostly to do with where the foucus ends up after pressing OK on the messagebox.
Rolf Brandt
http://www.rbsoft.eu
http://www.taxifreeware.com
I cook with wine, sometimes I even add it to the food.
(W. C. Fields)

Cho Sing Kum

#17
Hi Rolf,

I have to correct myself on the PBForms example.

On Startup, it is like the one in FF. But after pressing the <Enter> key, it behave like VB6, no longer like FF.

Quote from: Rolf Brandt on March 25, 2010, 09:54:19 AM
I think the test program would have been better it we would have another control on it like a text box to see how the program behaves. I tried it also with PwrDef and EZGui DDT. I noticed all act a little different which has mostly to do with where the foucus ends up after pressing OK on the messagebox.

The input focus should return back to the Command Button that has the input focus and that trigger the messagebox.

But I think this is not the problem as long as the Command Button that has the input focus on startup is also the default (as in tab to). After taht, things should be okay already.

Rolf Brandt

Exactly, it puts the focus afterwards on the Hello button.
Rolf Brandt
http://www.rbsoft.eu
http://www.taxifreeware.com
I cook with wine, sometimes I even add it to the food.
(W. C. Fields)

Roger Garstang

#19
VB isn't a good comparison.  It has its own internal engine.  Examining both it and the PB versions show totally different results. The buttons in the VB app aren't even Button Class windows.  Neither button even has button styles including no Default Button style like the PB versions both have.  It is like an app built with Delphi or some other big tool that doesn't even use real windows half the time but internal classes that it just draws and does its own thing with.  On startup both PB versions have all the proper messages, notifications, and a SetFocus...the VB is missing about half of them and never even fires a SetFocus so it is all drawn and handled internal.  To have it startup and draw like VB you'd need to handle the Default Button and tabs/arrows, etc yourself in a full True Windowed app where you handle all keys and tab order yourself.  You'd soon find out it is a pain and all kinds of problems though.  FF used to do it this way, but like most of the other PB designers including DDT, Paul has made it use Dialog Message processing so the Def Proc for Dialogs is used to automatically handle it all (WM_GETDLGCODE is usually sent to determine all the buttons and tab orders).

One way to possibly mimic VB would be to set the Default Button on load along with the Focus(No need for an additional SetFocus though as the first in tab order already gets a SetFocus in FF).  So just set the Button to Default then once the form is displayed and the button has focus turn it off and set it back to the original...and if WM_GETDLGCODE/DM_GETDEFID is sent again by IsDialogMessage it should reset everything back to normal.  Or your first tab order button could just be your Default button, then no issue.

Another test to see if VB behaves right is to put a textbox on that form and make it first in tab order then the non-default button then the default, and when tabbing from textbox to non-default to compare.  In PB apps it only becomes Default if focus comes from a default button (most likely due to how it handles one event at a time and looks at each event/control as they come in dialog processing).

Rolf Brandt

Hi Roger,

I tried that here with VB and a couple of PB designers. Put a textbox on it, set focus to textbox. All fire the CommandButton set to default and return focus to the textbox.
Rolf Brandt
http://www.rbsoft.eu
http://www.taxifreeware.com
I cook with wine, sometimes I even add it to the food.
(W. C. Fields)

Roger Garstang

Hmm, looks like Paul doesn't block all messages in FF IDE too, when you click buttons it gives them focus and the default style(Only Command2 should be orange)...and playing with all this appears to have screwed up my tooltips.



Also, here is what I meant on the app:  http://www.garstangs.net/Project1.zip

Tab normally and the 1st button never gets default, Shift+Tab to go backwards and it does.

I also monitored the messages to the first command button while doing this and on every Tab press WM_GETDLGCODE is sent to all controls.  On normal Tab only SetFocus is done, on the reverse a BM_SETSTYLE is sent to it setting and removing the BS_DEFPUSHBUTTON by the dialog process...pretty interesting how Microsoft's Dialog procedure doesn't handle the buttons how they are documented to be handled.

Cho Sing Kum

Quote from: Roger Garstang on March 25, 2010, 04:31:17 PM
VB isn't a good comparison.  It has its own internal engine.  Examining both it and the PB versions show totally different results. The buttons in the VB app aren't even Button Class windows.  Neither button even has button styles including no Default Button style like the PB versions both have.  It is like an app built with Delphi or some other big tool that doesn't even use real windows half the time but internal classes that it just draws and does its own thing with.  On startup both PB versions have all the proper messages, notifications, and a SetFocus...the VB is missing about half of them and never even fires a SetFocus so it is all drawn and handled internal.
It is a known fact that VB has its own runtime to handle its stuff. However it does things, it is also important to acknowledge that the end result is a GUI behaviour that is consistent with Windows' behaviour.

Quote from: Roger Garstang on March 25, 2010, 04:31:17 PM
Neither button even has button styles including no Default Button style like the PB versions both have.
I cannot see anything different between the Buttons created by FF and VB6, whether classic or XP theme. Unless I misunderstand you.

Quote from: Roger Garstang on March 25, 2010, 04:31:17 PM
To have it startup and draw like VB you'd need to handle the Default Button and tabs/arrows, etc yourself in a full True Windowed app where you handle all keys and tab order yourself.  You'd soon find out it is a pain and all kinds of problems though.

To have it start up and draw like VB (we are talking here specifically about the command button button with the first tabstop not getting default) is to expect the startup GUI to be according to Windows' guideline, isn't it?

How VB6 does it, and it does it right, is not relevant here in this specific problem. FireFly is a GUI and RAD tool. This is the reason why I am using it. And I expect it to start up and draw in its own way to standard Windows behaviour.

Quote from: Roger Garstang on March 25, 2010, 05:07:59 PM
Also, here is what I meant on the app:  http://www.garstangs.net/Project1.zip

Tab normally and the 1st button never gets default, Shift+Tab to go backwards and it does.
Your example sidetrack from the problem in the first post. But it show up another problem.

I created one like yours with PBForms 2.01, attached with codes and exe. Button1, the non-default button, gets the default visual when tab to it both forward and backward.

Rolf Brandt

Rolf Brandt
http://www.rbsoft.eu
http://www.taxifreeware.com
I cook with wine, sometimes I even add it to the food.
(W. C. Fields)

Rolf Brandt

#24
Roger,

the example with the RichEdit is not ideal, because the RichEdit control is multiline. So it will catch and execute the Enter keys. The same happens if you use a multiline textbox. If a textbox is not multiline then the button that is set to BS_DEFPUSHBUTTON will fire.

Here VB6's ThunderRT6 textbox does not work the same - even if it is set to multiline the DefPushButton will fire. So if you are using muliline textboxes on a VB6 form you can not use a button that is set as Default=True.

In most other things the VB6 ThunderRT6 classes behave of course conform to Windows.

By the way aren't we getting lost a little from the original problem that the this thread addressed???
Rolf Brandt
http://www.rbsoft.eu
http://www.taxifreeware.com
I cook with wine, sometimes I even add it to the food.
(W. C. Fields)

Roger Garstang

I don't think we are getting sidetracked at all from the problem...in fact the last page here is probably closer to solving it than the first.  To Answer Cho's question on VB which Rolf already posted about the Thunder RT6 classes is that, like we already know when using something like WinSpector, VB isn't using the same "engine" to process input.  That engine being the dialog way of processing.  And, while they look like buttons in VB they are not true buttons.  A better comparison would have been a straight C++ app...possibly even one not created in VS.

The PBforms app just posted though is interesting in that DDT fixes one of the two problems, so while it exibited the same problem of not having the button as default on Load it does do it bi-directional.  Since it has been said many times over at the PB forums that DDT uses the dialog based processing that is the same as what FF uses then they must have a step Paul missed to get bi-directional.  I think it can be solved with WM_GETDLGCODE.  He already has a "patch" so to speak to allow tabbing out of multi-line text boxes that while non-standard I like...one step further would be perhaps a test along the same lines of checking the next control to get focus with WM_GETDLGCODE and if it doesn't return DLGC_DEFPUSHBUTTON we set the style just as I saw above when monitoring the messages.  Sometimes it may send the set style twice setting the same style, but at least it will be set correctly.  Same thing during the first set focus, or perhaps monitoring SetFocus messages so if someone calls it in code it will do it as well.  This would then solve all problems.

Roger Garstang

#26
Just confirmed that DDT/PBforms does most of the same steps as FF apps, just a couple missing.  For some reason when a control gets focus WM_GETDLGCODE is sent to it 4 times and when it loses focus it gets WM_GETDLGCODE sent to it twice. Holding shift also rapidly sends WM_GETDLGCODE to all controls.  The problem seems to be that the dialog processing only cares about focus leaving a default button. In the PBforms app when I tab from the textbox to the default it gets the 4 WM_GETDLGCODE messages and redundantly sets itself to non default then back when it was already default from the focus being in the text box.  The FF app didn't do anything when focus changed from textbox to default button.  So, DDT does additional things.  When focus went from default to another control they both behaved the same as well.

So, I think what we need is just the initial focus if a button is not set to default in WM_SETFOCUS messages and when coming from any control not returning DLGC_DEFPUSHBUTTON from WM_GETDLGCODE to a button also not returning DLGC_DEFPUSHBUTTON since those are the only ones missing. The DLGC values are also OR'd, so will need to boolean test for the DLGC_DEFPUSHBUTTON bit.

Roger Garstang

I had a big complicated procedure checking current and next control and only changing if coming from and going to certain types, etc...but ended up just fixing it with this at the end of the WM_SETFOCUS case in the Form CodeProc in the generated Form.inc file (Right before your own code that is the subclass function for every control):


       If (SendMessage(hWndControl, %WM_GETDLGCODE, 0, 0) And %DlgC_UnDefPushButton) = %DlgC_UnDefPushButton Then ' Button and Not Default
           DefButton= GetDlgItem(GetParent(hWndControl), 1)
           If DefButton <> 0 Then SendMessage(DefButton, %BM_SETSTYLE, %BS_PushButton, %TRUE)
           If DefButton <> wParam Then SendMessage(hWndControl, %BM_SETSTYLE, %BS_DefPushButton, %TRUE)
        End If

Roger Garstang

#28
Logic with that may need some work.  I tried it without a Default button declared and it seems to reverse the logic and it stops the first setfocus from working since prev focused item is nothing so wParam= 0 along with the default button then being 0.  Then the multiline textboxes/richedit mess with it.  Paul may need to modify his tweak for multiline tabbing to return something different for them in WM_GETDLGCODE or something so they don't capture Tab but still get the keys they need.  Too many variables to keep track of and make it all work.  Personally I'm fine with it behaving how it does since I've been using Windows from 3.0 days and use a lot of the old key navigation M$ changed in Win95+, but luckily kept it so far for backwards compat.  I've always used spacebar for buttons and enter only for default button.  Maybe if someone is liked by Bob they could ask him how he handled it in the PB forum...perhaps he has a better way we could combine with this.

FWIW- Phoenix has the same issues and more (On entry the first button gets focus and no default like FF/DDT, and when tabbing for some reason it will actually remove the default border on the 2nd button then it comes back next cycle which is weird because I see no custom code doing anything special other than it had no themes and it only passes the message to the Dialog handler like FF does)...plus it appears to force all of your Default buttons to be labeled OK.  I created the same app in it hoping it would shed some light on things since he knows a lot about all the inside stuff and shares his knowledge better than PB...but it didn't get any further.

John Montenigro

Whew! Having been away for awhile, there's a lot to catch up on!!!

Although I've read the 2 pages of this thread twice, I know I'm missing something. I haven't had a chance to try all the test code yet, so that might be what I'll do this week.

However, for me personally, it would be most helpful if someone could provide a clearly written set of guidelines that provides guidance on what's the right/best thing to do in the various situations.

For example:
- If you want to load a form and have a particular command button be the default and have focus (to ignore what the user types and only accept Enter), then do these things...(show code)
- If you want to load a form and have a textbox receive keystrokes while a command button receives Enter, then do these things...(show code)
- If...(show code)

In this way, the result of all this testing is that we have captured the "right" things to do so that we don't have to figure them out each time in the future...especially helpful to those of us who aren't programming everyday and need a periodic "quick-reference" refresher...

Thanks,
-JohnM