Question about focus

Started by Wilko Verweij, June 13, 2017, 06:57:58 PM

Previous topic - Next topic

Wilko Verweij

Hi all,
I have a question about focus in Firefly freebasic. I had a problem that I did not understand. To make it easier, I made a very simple test program which has the same problem as my real-world-program. Just one small window, two buttons, both 'push buttons', no 'default button', one of the has the 'cancel'-property set. Both have ws_tabstop property set. First button is on top of tab order. No additional code written by me. Compiles fine. When I start the program, it looks like in P1.png. Does not look strange so far, but when I press tab, the cancel-button (which then receives the focus) looks quite different. And if I press tab again, focus goes back to first button but then looks like picture P2. What I would like is that the initial view is like the P2 picture. How can I do that? Any help is appreciated...
Wilko

José Roca

> What I would like is that the initial view is like the P2 picture. How can I do that?

Sey the focus in the OK button.

Wilko Verweij

Sorry, I forgot to mention that I tried SetFocus, in the FORM1_WM_CREATE Function. So apparently that's not the right place. Where should I put it?

José Roca

Post a custom message, e.g.


PostMessage hWnd, %WM_USER + 999, hButton, 0


and then set the focus when processing that message


CASE %WM_USER + 999
   IF wParam THEN SetFocus wParam



José Roca

#5
Why not? The only requisite is that it must be unique.

Pierre Bellisle

#6
Hey,

For me SetFocus() work with or without a PostMessage() if I do not use CommonControl6 via a manifest.
If I use a CommonControl6 then SetFocus() won't do it alone. I got to add
SendMessage(hWnd, WM_CHANGEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), 0)

But to really mimic the behavior I think Wilko want, I got to use this not so clean method to simulate a TAB and a SHIFT-TAB
SetFocus(handleOfMyButton)
KeyBd_Event VK_TAB, 0, 0, 0
KeyBd_Event VK_TAB, 0, KEYEVENTF_KEYUP, 0
KeyBd_Event VK_SHIFT, 0, 0, 0
KeyBd_Event VK_TAB, 0, 0, 0
KeyBd_Event VK_TAB, 0, KEYEVENTF_KEYUP, 0
KeyBd_Event VK_SHIFT, 0, KEYEVENTF_KEYUP, 0


Pierre

Wilko Verweij

OK, thank you all for your suggestions. I am going to test them later this week.

José Roca

Posting a message and setting the focus when processing that message has always worked for me.

Anyway, since using CWindow, I no longer need to use it because I add the controls after the main window has been created, not in WM_CREATE.

Pierre Bellisle

Hola Jose,

I think that Wilco is interested not only in the focus but also in the look his button have.
Meaning the focus dotted line and the highlighted button edge.

I did some quick test on Windows 7 and 10, with Common control 6.0 and 5.82,
And SetFocus/KeyBd_Event, SetFocus/WM_CHANGEUISTATE, PostMessage/SetFocus.

Results are in the code, in the "Select Case" section. :-)

Pierre
#Define JumpCompiler "<D:\Free\64\fbc.exe>"
#Define JumpCompilerCmd "<-s gui "D:\Free\bas\~~Default.rc">"
#define unicode
#Include Once "windows.bi"
#Include Once "win\shellapi.bi" 'ExtractIcon()

ENUM
  ButtonOk  = 101
  ButtonEsc
END ENUM

#Define AppName "Focus"

Dim Shared As HINSTANCE hInstance : hInstance = GetModuleHandle(NULL)
'______________________________________________________________________________

Function WndProc(hWnd As HWND, uMsg As UINT, wParam As WPARAM, lParam As LPARAM) As Integer
Static hButtonOk    As HWND
Dim    hButtonEsc   As HWND
Static hFont        As HFONT

Select Case (uMsg)

   Case WM_CREATE
     Function = False
     hFont = GetStockObject(DEFAULT_GUI_FONT)

     hButtonOk = CreateWindowEx(0, "Button", "&OK", _
                                WS_CHILD Or WS_VISIBLE Or WS_TABSTOP Or WS_GROUP Or _
                                BS_CENTER Or BS_VCENTER, _
                                25, 15, 80, 30, _
                                hWnd, Cast(HMENU, ButtonOk), _
                                hInstance, NULL)
     SendMessage(hButtonOk, WM_SETFONT, Cast(UInteger, hFont), TRUE)

     hButtonEsc = CreateWindowEx(0, "Button", "&Cancel", _
                                 WS_CHILD Or WS_VISIBLE Or BS_CENTER Or WS_TABSTOP Or _
                                 BS_NOTIFY Or BS_TEXT Or BS_VCENTER, _
                                 135, 15, 80, 30, _
                                 hWnd, Cast(HMENU, ButtonEsc), _
                                 hInstance, NULL)
     SendMessage(hButtonEsc, WM_SETFONT, Cast(UInteger, hFont), TRUE)

     Dim As Long TryOption = 1 '+ 1 + 1
     Select Case TryOption

       Case 1
         'Button "OK" start with dotted line and highlighted  edge if CommonControl 6.0   (Win 10 and Win 7)
         'Button "OK" start with dotted line and no highlight edge if CommonControl 5.82  (Win 10 and Win 7)
         SetFocus(hButtonOk)
         KeyBd_Event VK_TAB, 0, 0, 0
         KeyBd_Event VK_TAB, 0, KEYEVENTF_KEYUP, 0
         KeyBd_Event VK_SHIFT, 0, 0, 0
         KeyBd_Event VK_TAB, 0, 0, 0
         KeyBd_Event VK_TAB, 0, KEYEVENTF_KEYUP, 0
         KeyBd_Event VK_SHIFT, 0, KEYEVENTF_KEYUP, 0

       Case 2
         'Button "OK" start with dotted line and no highlighted edge if CommonControl 6.0  (Win 10 and Win 7)
         'Button "OK" start with dotted line and no highlighted edge if CommonControl 5.82 (Win 10 and Win 7)
         SetFocus(hButtonOk) 'SetFocus alone is ok if no CommControl6
         SendMessage(hWnd, WM_CHANGEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), 0)

       Case 3
         'Button "OK" start with no dotted line and no highlight edge if CommonControl 6.0  (Win 10 and Win 7)
         'Button "OK" start with    dotted line and no highlight edge if CommonControl 5.82 (Win 10 and Win 7)
         PostMessage(hWnd, WM_APP, 0, 0)

     End Select

   Case WM_APP
     SetFocus(hButtonOk)

   Case WM_CHANGEUISTATE

   Case WM_COMMAND
     Select Case LoWord(wParam)

       Case ButtonOk
         If HiWord(wParam) = BN_CLICKED Then
           _Beep(1500, 100)
         EndIf

       Case ButtonEsc, IDCANCEL
         If HiWord(wParam) = BN_CLICKED Then
           PostMessage(hWnd, WM_CLOSE, 0, 0)
           Exit Function
         EndIf

     End Select

   Case WM_DESTROY
     DeleteObject(hFont)
     PostQuitMessage(0)
     Exit Function

End Select

Function = DefWindowProc(hWnd, uMsg, wParam, lParam)

End Function
'_____________________________________________________________________________

Function WinMain(hInstance As HINSTANCE, hPrevInst As HINSTANCE, _
                 CmdLine As WString Ptr, CmdShow As Integer) As UINT
Dim WinClass   As WNDCLASS
Dim wMsg       As MSG
Dim hWnd       As HWND
Dim hIco       As HICON
Dim WindowSize As SIZEL
Dim wsAppName  As WSTRING * 128

wsAppName              = AppName & " - " & SizeOf(UInteger) * 8
WindowSize.cx          = 245
WindowSize.cy          = 90
hIco                   = ExtractIcon(hInstance, "%SystemRoot%\System32\PowrPrOf.dll", 1)
WinClass.style         = CS_HREDRAW Or CS_VREDRAW
WinClass.lpfnWndProc   = ProcPtr(WndProc)
WinClass.cbClsExtra    = 0
WinClass.cbWndExtra    = 0
WinClass.hInstance     = hInstance
WinClass.hIcon         = hIco
WinClass.hCursor       = LoadCursor(NULL, IDC_ARROW)
WinClass.hbrBackground = Cast(HGDIOBJ, COLOR_BTNFACE + 1) 'Default color
WinClass.lpszMenuName  = NULL
WinClass.lpszClassName = @wsAppName

If (RegisterClass(@WinClass)) Then
   hWnd = CreateWindowEx(WS_EX_WINDOWEDGE, _
                         wsAppName, wsAppName, _
                         WS_OVERLAPPED OR WS_CLIPCHILDREN Or WS_DLGFRAME Or WS_BORDER Or WS_VISIBLE Or WS_CAPTION Or _
                         WS_MAXIMIZEBOX Or WS_MINIMIZEBOX Or WS_SYSMENU , _
                         (GetSystemMetrics(SM_CXSCREEN) - WindowSize.cx) / 2, _ 'PosH
                         (GetSystemMetrics(SM_CYSCREEN) - WindowSize.cy) / 2, _ 'PosV
                         WindowSize.cx, WindowSize.cy, _ 'Width, height
                         NULL, NULL, hInstance, NULL)

   ShowWindow(hWnd, SW_SHOW)
   UpdateWindow(hWnd)

   While GetMessage(@wMsg, ByVal NULL, 0, 0) > 0
     If IsDialogMessage(hWnd, @wMsg) = 0 Then
         TranslateMessage(@wMsg)
         DispatchMessage(@wMsg)
     End If
   Wend

  End If
  DestroyIcon(hIco)
  Function = wMsg.message

End Function
'_____________________________________________________________________________

End WinMain(hInstance, NULL, Command(), SW_NORMAL) 'Call main() and return the error code to the OS
'_____________________________________________________________________________
'


José Roca

I see. I didn't pay enough attention to the pictures.

BTW I advice you to specify BYVAL or BYREF in the parameters of your functions, e.g.


Function WinMain(BYVAL hInstance As HINSTANCE, BYVAL hPrevInst As HINSTANCE, _
                 BYVAL CmdLine As WString Ptr, BYVAL CmdShow As Integer) As UINT


Otherwise you will get errors if compiled using the "pedantic" option.

Wilko Verweij

Thank you guys. This really helps.
Wilko