Page 1 of 1

Keyboard Focus and Threads

Posted: Thu Jun 18, 2009 2:20 pm
by Polly
Does anybody have an idea why window/gadget 0 does not get the keyboard focus, whatever I do?

Code: Select all

Procedure test(x)
   hwnd=OpenWindow(1, 0, 0, 256, 99, "", #PB_Window_ScreenCentered  )
   If hwnd
      TextGadget(#PB_Any, 50, 10, 170, 70, "xxx", #PB_Text_Center)
   EndIf
   While WindowEvent() : Wend
   Delay(1500)
   CloseWindow(1)
EndProcedure

test=CreateThread(@test(),0)
While IsThread(test) : Delay(100) : Wend 

  If OpenWindow(0, 0, 0, 322, 35, "StringGadget Flags", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    StringGadget(0, 8,  10, 306, 20, "Normal StringGadget...")
    StickyWindow(0,1)
    StickyWindow(0,0)
    SetActiveWindow(0)
    Debug WindowID(0)
    Debug SetFocus_(WindowID(0))
    Debug GetFocus_()
    SetActiveGadget(0)
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf
Keyborad focus has ... the debugger! (XP, 4.31, x86)

Posted: Thu Jun 18, 2009 4:20 pm
by srod
Curious. Remove all debugs and we are still left with the problem.

Using Purebasic event loops in a thread is perhaps not such a great idea. However, I can see no immediate reason why this should fail to work as expected. If you move the 'While IsThread(...)...' after the OpenWindow() then I can get it to work easily enough.

A better workaround perhaps :

Code: Select all

Procedure test(x) 
  hwnd=OpenWindow(1, 0, 0, 256, 99, "", #PB_Window_ScreenCentered  ) 
  If hwnd 
    TextGadget(#PB_Any, 50, 10, 170, 70, "xxx", #PB_Text_Center) 
  EndIf 
  While WindowEvent() : Wend 
  Delay(1500) 
  CloseWindow(1) 
EndProcedure 

test=CreateThread(@test(),0) 
While IsThread(test) : Delay(100) : Wend 

hWnd = OpenWindow(0, 0, 0, 322, 35, "StringGadget Flags", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_Invisible) 
If hWnd
  ShowWindow_(hWnd, #SW_MINIMIZE)
  ShowWindow_(hWnd, #SW_RESTORE)

  StringGadget(0, 8,  10, 306, 20, "Normal StringGadget...") 

  SetActiveGadget(0) 
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow 
EndIf 

Posted: Thu Jun 18, 2009 4:38 pm
by ABBKlaus
or use SetWindowState() :wink:

Code: Select all

  SetWindowState(0,#PB_Window_Minimize)
  SetWindowState(0,#PB_Window_Normal)

Posted: Thu Jun 18, 2009 4:43 pm
by srod
ABBKlaus wrote:or use SetWindowState() :wink:

Code: Select all

  SetWindowState(0,#PB_Window_Minimize)
  SetWindowState(0,#PB_Window_Normal)
Good point! :)

Posted: Thu Jun 18, 2009 5:01 pm
by netmaestro
Fine but the question of why the window needs restored remains. Not only is it not getting activated, when the second window opens, if you don't use StickyWindow, it comes out behind the ide.

Posted: Thu Jun 18, 2009 5:15 pm
by srod
netmaestro wrote:Fine but the question of why the window needs restored remains. Not only is it not getting activated, when the second window opens, if you don't use StickyWindow, it comes out behind the ide.
Not here on Vista. Comes up on top.

Posted: Thu Jun 18, 2009 5:18 pm
by netmaestro
I'm currently test-driving Win7 RC and if I comment out the StickyWindow code it's coming out behind the ide.

Posted: Thu Jun 18, 2009 5:32 pm
by netmaestro
The thread is gone and so is the window it created, so isn't this a bug? Sure seems like one at this point unless I'm missing something.

Posted: Thu Jun 18, 2009 5:39 pm
by srod
Hard to say if this constitutes a PB bug in this case. Personally I wouldn't attempt such things with threads anyhow as this is just asking for trouble! :)

Re: Keyboard Focus and Threads

Posted: Thu Jun 18, 2009 9:50 pm
by PB
> why window/gadget 0 does not get the keyboard focus

It gets the focus here just fine (Win XP + SP2).

Posted: Thu Jun 18, 2009 10:10 pm
by srod
When I run the original code on XP here, the string gadget doesn't get the focus. You should be able to type directly into the string gadget without first clicking it.

Posted: Thu Jun 18, 2009 11:08 pm
by idle
Don't really know what's going on there at all. This works though

Code: Select all

Procedure test(x)
   hwnd=OpenWindow(1, 0, 0, 256, 99, "", #PB_Window_ScreenCentered,x)
   If hwnd
      TextGadget(#PB_Any, 50, 10, 170, 70, "xxx", #PB_Text_Center)
   EndIf
   While WindowEvent() 
   Delay(0)
   Wend
   Delay(300)
   CloseWindow(1)
    tID1 = 0
EndProcedure 

Procedure test2(x)

 OpenWindow(2, 0, 0, 322, 35, "StringGadget Flags", #PB_Window_SystemMenu | #PB_Window_ScreenCentered,x)
 StringGadget(0, 8,  10, 306, 20, "Normal StringGadget...")
 SetActiveGadget(0)
 Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow 
 tID2 = 0

EndProcedure 

Global tID1,tID2 

 If OpenWindow(0, 0, 0, 322, 35, "StringGadget Flags", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
      
   Repeat 
      ev = WaitWindowEvent()
      If ev = #WM_LBUTTONDOWN
         If Not IsThread(tID1)  
           tID1 = CreateThread(@test(),WindowID(0))
         EndIf  
      ElseIf ev = #WM_RBUTTONDOWN
         If Not IsThread(tID2)  
           tID2 = CreateThread(@test2(),WindowID(0))
         EndIf  
      EndIf 
    
    Until ev = #PB_Event_CloseWindow
  
  EndIf 

[/code]

Posted: Fri Jun 19, 2009 8:54 am
by Polly
Thanks all for your support. For my purpose the Minimize workaround is sufficient, using Stickywindow to force the window opening on top, which is required on XP too.

But generally speaking I would also consider it as a bug as there is no reasonable explanation to be seen. When the second window opens only the main thread is running - and so it should work as usual.

Posted: Fri Jun 19, 2009 9:04 am
by Polly
With Minimize the StickyWindow is not neccessary of course.