SetFocus ..how to?

Started by Zlatko Vid, April 05, 2023, 10:16:11 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Zlatko Vid

All work until i tested my old examples with arrow keys,tab key ,enter key not work
then i find that i need to modify message loop in a different way ,
why that is ..is because that keyboars buttons are used with Dialogs

so now message loop is this :

'/// message loop ///
WHILE GetMessage (wm,0,0,0)<>0
    if IsDialogMessage(win,wm) = 0
       TranslateMessage wm
       DispatchMessage wm
    else
     TranslateMessage wm
     DispatchMessage wm
   end if
 WEND
  •  

Pierre Bellisle

Hi Aurel,

Since you always do a  TranslateMessage() and a  DispatchMessage() no matter what.
In definitive your message loop is an equivalent to the following.

'/// message loop ///
WHILE GetMessage(wm, 0, 0, 0) <> 0
  TranslateMessage(wm)
  DispatchMessage(wm)
WEND

Can you post a little code example of what you got so we can see what it's all about.

Regard,
Pierre
  •  

Charles Pegge

Hi Pierre,

checkout IsDialogMessage. It does more than the name suggests. It modifies the keyboard code filters.

This should work:

'/// message loop ///
WHILE GetMessage (wm,0,0,0)<>0
   IsDialogMessage(win,wm)
   TranslateMessage wm
   DispatchMessage wm
 WEND

Zlatko Vid

Hi Piere ...hi Charles

>> It modifies the keyboard code filters. <<

Yes that is a my main problem and of course i will post code

i try with this :
and kind a work :

'================================================================
'/// message loop ///
WHILE GetMessage (wm,0,0,0)<>0

    if IsDialogMessage(win,wm) = 0
       'TranslateMessage wm
       'DispatchMessage wm
    end if
 
    if GetMessage (wm,0,0,0) <> 0
       TranslateMessage wm
       DispatchMessage wm
    end if

 WEND
'================================================================
Function WndProc (sys hwnd,wmsg,wparam,lparam) as sys callback
win = hwnd
SELECT hwnd
CASE win
Select wmsg

     CASE WM_PAINT
          'paintstruct ps
          BeginPaint win,ps
          BitBlt(hDC, 0, 0, ww, wh, hdcMem, 0, 0, SRCCOPY)
          'InvalidateRect(win, 0, 0)
          '
         ReleaseDC( win, hDC)
         EndPaint win,ps

    'CASE WM_SETFOCUS
     '    SetFocus win

'processing windows messages by Interpreter..................................................
CASE WM_MOUSEMOVE
'hMouseX = LoWord(lParam)
'hMouseY = HiWord(lParam)
         'call block winMsg
         if pos_wmMouseMove > 0
            hMouseX = LoWord(lParam)
   hMouseY = HiWord(lParam)
            tc = pos_wmMouseMove : tokInterpreter()
            tc = 0         
        end if
'keybord event...............................................................................
CASE WM_KEYDOWN
         hWParam = wParam
         'call block winMsg
         if pos_wmKeyDown <> 0
            'print "KEYDOWN:" + str(pos_wmKeyDown)
            tc = pos_wmKeyDown : tokInterpreter()
            tc = 0
         end if
'............................................................................................
    CASE WM_COMMAND
         controlID = LoWord(wParam)  'get control ID
         notifyCode = HiWord(wParam) 'get notification message
         'hWParam = wParam
         Select controlID
         hwParam = controlID

            CASE IDOK
            'call block winMsg
            if notifycode = 0
             
              if pos_wmCommand > 0
                 tc = pos_wmCommand : tokInterpreter()
                 tc = 0
              end if
            end if

           'CASE IDCANCEL
            '  print "ID_CANCEL"

       End Select




..above is whole code i currently use in my interpreter

so as you may see i need both
  •  

Zlatko Vid

Sorry Charles your method not work
because when i entering text in edit control insted of one sign i get 4 signs pressing one
keyboard key.. i don't know why but might be connected with tab sequence
default is 4 i think

so my question is what IsDialogMessage do ?
is just TranslateMessage or DispatchMessage or both ?
  •  

Zlatko Vid

also ..well i found one guy on google group use it with PeekMessage
hmm i can try :
here is C code i  guess:

while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
BOOL bRet = ::GetMessage(&msg, NULL, 0, 0);
if(bRet == -1 || !bRet)
{
m_bQuit = TRUE;
continue;
}

HWND hWnd = msg.hwnd;

switch(msg.message)
{
//Find the parent dialog if there is one so IsDialogMessage will
work
case WM_CHAR:
case WM_SYSCHAR:
case WM_KEYUP:
case WM_KEYDOWN:
case WM_SYSKEYUP:
case WM_SYSKEYDOWN:
{
HWND hWndParent = _GetAncestor(hWnd, GA_PARENT);
if(hWndParent && hWndParent != HWND_DESKTOP)
hWnd = hWndParent;
}
break;
}

if(!IsDialogMessage(hWnd, &msg))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
  •  

Zlatko Vid

i try under peekMessage and not work ...

case else
         'peekmsg
          if PeekMessage (wm,0,0,0,Pm_Remove)>0 ' //peek
           'iF wm.message = WM_QUIT : DeleteDC(hdc) : end if
           TranslateMessage (wm)
           DispatchMessage (wm)
         
          else
            IsDialogMessage(win,wm)
             TranslateMessage (wm)
             DispatchMessage (wm)
          'end if
         end if
  •  

Zlatko Vid

strange .no mather i try i have keyboard key delay
not respond well
  •  

Charles Pegge

Which Oxygen version are you using? I've picked up a problem with 060 which might be connected.

Zlatko Vid

Charles i am using old A043 and so far all api calls work well
i really don't know how this work in PowerBasic or PureBasic or FreeBasic
because i cannot found any similar example
  •  

Zlatko Vid

Charles
the closest example i found here posted by Jose
and is about subclassing textbox or edit control
i compiled it in A043 and seems that work well i add small char[] buffer to view entered text


$ filename "SubClassText.exe"
uses rtl32
uses MinWin
uses User
uses Comctl

char txBuff[256]
sys hEdit
string crlf = chr(13) + chr(10)
#lookahead

%GWLP_WNDPROC = -4

function WinMain() as sys

   WndClass wc
   MSG      wm
   sys inst = GetModuleHandle 0

   sys hwnd, wwd, wht, wtx, wty, tax

   wc.style = CS_HREDRAW or CS_VREDRAW
   wc.lpfnWndProc = &WndProc
   wc.cbClsExtra = 0
   wc.cbWndExtra = 0   
   wc.hInstance = GetModuleHandle 0
   wc.hIcon=LoadIcon 0, IDI_APPLICATION
   wc.hCursor=LoadCursor 0,IDC_ARROW
   wc.hbrBackground = GetStockObject WHITE_BRUSH
   wc.lpszMenuName =0
   wc.lpszClassName =@"Demo"

   RegisterClass (&wc)

   Wwd = 320 : Wht = 200
   Tax = GetSystemMetrics SM_CXSCREEN
   Wtx = (Tax - Wwd) /2
   Tax = GetSystemMetrics SM_CYSCREEN
   Wty = (Tax - Wht) /2

   hwnd = CreateWindowEx(0,wc.lpszClassName,"OXYGEN BASIC",WS_OVERLAPPEDWINDOW,Wtx,Wty,Wwd,Wht,0,0,inst,0)

    hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, _
                              "Edit", _
                              "", _
                              WS_CHILD OR WS_VISIBLE OR WS_TABSTOP, _
                              20, 30, _
                              250, 25, _
                              hWnd, 102, _
                              inst, 0)
   SetWindowSubclass hEdit, &EditSubclassProc, 102, 0
   SetFocus hEdit

   ShowWindow hwnd,SW_SHOW
   UpdateWindow hwnd

   WHILE GetMessage(&wm, 0, 0, 0) > 0
      IF IsDialogMessage(hWnd, &wm) = 0 THEN
         TranslateMessage(&wm)
         DispatchMessage(&wm)
      END IF
   WEND

End Function

function WndProc (sys hWnd, uint wMsg, sys wParam, sys lparam) as sys callback
'==================================================================

    SELECT wMsg
       
      CASE WM_CREATE
         EXIT FUNCTION


      CASE WM_COMMAND
         SELECT CASE LOWORD(wParam)
            'test idok - "ENTER key pressed!"
            Case IDOK
                  if hiword(wparam) = BN_CLICKED
                      ' get editbox text
                      SendMessage hEdit, WM_GETTEXT, 256, strptr txbuff
                      'show message box
                      print "ENTER key pressed!" + crlf + txbuff
                  end if

            CASE IDCANCEL
               ' // If the Escape key has been pressed...
               IF HIWORD(wParam) = BN_CLICKED THEN
                  ' // ... close the application by sending a WM_CLOSE message
                  SendMessage hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_DESTROY
         PostQuitMessage 0

    END SELECT

   function = DefWindowProc hWnd,wMsg,wParam,lParam

end function ' WndProc

FUNCTION EditSubclassProc (sys hWnd, uint wMsg, sys wParam, sys lparam, uIdSubclass, dwRefData) as sys callback

   SELECT CASE wMsg
      CASE WM_DESTROY
         ' // REQUIRED: Remove control subclassing
         RemoveWindowSubclass hwnd, &EditSubclassProc, uIdSubclass

      CASE WM_KEYDOWN
         SetWindowText GetParent(hwnd), "ASCII " & STR(wParam)

   END SELECT

   FUNCTION = DefSubclassProc(hwnd, wMsg, wParam, lParam)

END FUNCTION


WinMain()
  •  

Zlatko Vid

#41
Jose example use subclassed edit control which is fine for
his example ....
but also work in my case with one my example
now because notification message is BN_CLICKED
i used before notifycode = 0
and probably because of this there is delay in execution
how will work in combination with WM_KEYDOWN ..i need to test

CASE WM_COMMAND
        controlID = LoWord(wParam)  'get control ID
        notifyCode = HiWord(wParam) 'get notification message
        'hWParam = wParam
        Select controlID
        hwParam = controlID

            CASE IDOK
            'call block winMsg
            if notifycode = BN_CLICKED           
              if pos_wmCommand > 0
                tc = pos_wmCommand : tokInterpreter()
                tc = 0
              end if
            end if

          'CASE IDCANCEL
            '  print "ID_CANCEL"


and message loop is here :

'/// message loop ///
WHILE GetMessage (wm,0,0,0) > 0

    if IsDialogMessage(win,wm) = 0
      TranslateMessage wm
      DispatchMessage wm
    end if

 WEND
 

..of course i must thanks to Jose   ;)
  •  

Charles Pegge

#42
I have never used dialogs, but that message loop now makes sense:

WHILE GetMessage (wm,0,0,0) > 0
    if IsDialogMessage(win,wm) = 0
      TranslateMessage wm
      DispatchMessage wm
    end if
 WEND

However, if your intention is to pickup keyboard codes without being restricted by focus you can check all the unfiltered window handles and keyboard codes coming through the message loop.

You can also use this information to directly issue your own WM_COMMAND messages to WndProc with the main hWnd. This is the message loop I use in tools\Peroxide.o2bas which uses buttons and edit-boxes but has no menu or accelerator table

  while bRet := GetMessage (wm, 0, 0, 0)
    if bRet==-1
      mbox "windows message loop error "
      exit while
    else
      if wm.message=WM_KEYDOWN
       select wm.wparam
        '
        case 0x1B 'Esc
          SendMessage hwnd,WM_DESTROY,0,0
          continue do
        case 83 'S
          if GetAsyncKeyState(VK_CONTROL) and 0x8000
            SendMessage hWnd,WM_COMMAND, 4002, 0 'to save file
            continue do
          endif
        case 69 'E
          if GetAsyncKeyState(VK_CONTROL) and 0x8000
            SendMessage hWnd,WM_COMMAND, 4003, 0 'to run file
            continue do
          endif
        case VK_F9 'save file
          SendMessage hWnd,WM_COMMAND, 4002, 0 'to save file
          continue do
        case VK_F5 'exec file
          SendMessage hWnd,WM_COMMAND, 4003, 0 'to run file
          continue do
        case VK_F2 'color
          SendMessage hWnd,WM_COMMAND, 4005, 0 'to colorize
          continue do
        case VK_F1
          DisplayHelp
          continue do
        case VK_F3 '
          SendMessage hWnd,WM_COMMAND, 4001, 0 'to execute search
        case VK_F4 '
          SendMessage hWnd,WM_COMMAND, 4004, 0 'to execute word search
        case 0x0D 'CR / Enter
          if wm.hwnd=w[4]
            SendMessage hWnd,WM_COMMAND, 4001, 0 'to execute search
            continue do
          endif
        end select
      endif
      TranslateMessage &wm
      DispatchMessage &wm
    endif
  wend

Zlatko Vid

Thank you Charles
I know that i miss something and that is :

 if GetAsyncKeyState(VK_CONTROL) and 0x8000

GetAsyncKeyState ..PeterW use in his programs

also i don't use Dialogs in my programs

but..

i do one little trick in my interpreter to
make it work ..at first i don't figured why work
but now i understand..i do this
 
// micro(A) code //
while wp ! 27  ' means NOT
'do nothing
wend

and that small empty loop enable use of arrow keys  ;)

all best
  •  

Pierre Bellisle

Charles> checkout IsDialogMessage. It does more than the name suggests.
Bill> Determines whether a message is intended for the specified dialog box and, if it is, processes the message.
Yes, you are quite right, I should have pay more attention...

Charles> I have never used dialogs, but that message loop now makes sense...
Could not agree more...

Aurel> so my question is what IsDialogMessage do ? is just TranslateMessage or DispatchMessage or both ?

Aurel, the message will be proceed by either IsDialogMessage or TranslateMessage/DispatchMessage, not both.

The remark section of IsDialogMessage is usefull:
If IsDialogMessage() return zero the message has not been processed so use TranslateMessage/DispatchMessage.
Although the IsDialogMessage function is intended for modeless dialog boxes, you can use it with any window that contains controls,
enabling the windows to provide the same keyboard selection as is used in a dialog box.
When IsDialogMessage processes a message,
it checks for keyboard messages and converts them into selections for the corresponding dialog box.
For example, the TAB key, when pressed, selects the next control or group of controls,
and the DOWN ARROW key, when pressed, selects the next control in a group.
Because the IsDialogMessage function performs all necessary translating and dispatching of messages,
a message processed by IsDialogMessage must not be passed to the TranslateMessage or DispatchMessage function.
IsDialogMessage sends WM_GETDLGCODE messages to the dialog box procedure to determine which keys should be processed.

Here is some code to demo WM_GETDLGCODE/DLGC_WANTALLKEYS on an edit control.
The control will get all keystroke, including tab, enter, esc, etc, etc.

//KickSwitch -32
//KickEnd

uses rtl32
uses MinWin
uses User
uses Comctl

sys hEdit

#lookahead

%Edit                    101
%GWLP_WNDPROC             -4
%DEFAULT_GUI_FONT         17
%WM_GETDLGCODE        0x0087
%DLGC_WANTARROWS      0x0001 // Direction keys.
%DLGC_WANTTAB         0x0002 // TAB key.
%DLGC_WANTALLKEYS     0x0004 // All keyboard input.
%DLGC_WANTMESSAGE     0x0004 // All keyboard input (the application passes this message in the MSG structure to the control).
%DLGC_HASSETSEL       0x0008 // EM_SETSEL messages.
%DLGC_DEFPUSHBUTTON   0x0010 // Default push button.
%DLGC_UNDEFPUSHBUTTON 0x0020 // Non-default push button.
%DLGC_RADIOBUTTON     0x0040 // Radio button.
%DLGC_WANTCHARS       0x0080 // WM_CHAR messages.
%DLGC_STATIC          0x0100 // Static control.
%DLGC_BUTTON          0x2000 // Button.
'____________________________________________________________________________

function WinMain() as sys
 WndClass WindowClass
 MSG      WindowMessage
 long     WindowWidth, WindowHeight, WindowPosX, WindowPosY
 sys      hWnd
 sys      inst = GetModuleHandle(0)

 WindowClass.style         = CS_HREDRAW | CS_VREDRAW
 WindowClass.lpfnWndProc   = &WndProc
 WindowClass.cbClsExtra    = 0
 WindowClass.cbWndExtra    = 0
 WindowClass.hInstance     = GetModuleHandle(0)
 WindowClass.hIcon         = LoadIcon(0, IDI_APPLICATION)
 WindowClass.hCursor       = LoadCursor(0,IDC_ARROW)
 WindowClass.hbrBackground = 16
 WindowClass.lpszMenuName  = 0
 WindowClass.lpszClassName = @"OXYGEN BASIC"
 RegisterClass (WindowClass)

 WindowWidth  = 320
 WindowHeight = 100
 WindowPosX   = (GetSystemMetrics(SM_CXSCREEN) - WindowWidth)  / 2
 WindowPosY   = (GetSystemMetrics(SM_CYSCREEN) - WindowHeight) / 2
 hWnd = CreateWindowEx(WS_EX_STATICEDGE, WindowClass.lpszClassName,
                       "WM_GETDLGCODE demo", WS_OVERLAPPEDWINDOW,
                       WindowPosX, WindowPosY, WindowWidth, WindowHeight, 0, 0, inst, 0)

 hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit", "Try [tab] [arrows] [enter]",
                        WS_CHILD OR WS_VISIBLE OR WS_TABSTOP,
                        20, 30, 270, 20,
                        hWnd, Edit, inst, 0)
 SendMessage(hEdit, WM_SETFONT, GetStockObject(DEFAULT_GUI_FONT), TRUE)
 SetWindowSubclass(hEdit, &EditSubclassProc, Edit, 0)
 SetFocus(hEdit)

 ShowWindow(hWnd, SW_SHOW)
 UpdateWindow(hWnd)

 while GetMessage(&WindowMessage, 0, 0, 0) > 0
   if IsDialogMessage(hWnd, &WindowMessage) = 0
     'if IsDialogMessage() return zero the message has not been processed
     'so use TranslateMessage/DispatchMessage
     TranslateMessage(&WindowMessage)
     DispatchMessage(&WindowMessage)
   end if
 wend

end function
'____________________________________________________________________________

function WndProc(sys hWnd, uint wMsg, sys wParam, sys lparam) as sys callback

 select wMsg

   case WM_DESTROY
     RemoveWindowSubclass(hEdit, &EditSubclassProc, Edit) 'unsubclass
     PostQuitMessage(0)

 end select

 function = DefWindowProc(hWnd, wMsg, wParam, lParam)

end function
'____________________________________________________________________________

function EditSubclassProc(sys hEdit, uint wMsg, sys wParam, sys lparam, uIdSubclass, dwRefData) as sys callback

 select case wMsg

   case WM_GETDLGCODE
     'DLGC_WANTARROWS      0x0001 Direction keys.
     'DLGC_WANTTAB         0x0002 TAB key.
     'DLGC_WANTALLKEYS     0x0004 All keyboard input.
     'DLGC_WANTMESSAGE     0x0004 All keyboard input (the application passes this message in the MSG structure to the control).
     'DLGC_HASSETSEL       0x0008 EM_SETSEL messages.
     'DLGC_DEFPUSHBUTTON   0x0010 Default push button.
     'DLGC_UNDEFPUSHBUTTON 0x0020 Non-default push button.
     'DLGC_RADIOBUTTON     0x0040 Radio button.
     'DLGC_WANTCHARS       0x0080 WM_CHAR messages.
     'DLGC_STATIC          0x0100 Static control.
     'DLGC_BUTTON          0x2000 Button.
     return DLGC_WANTALLKEYS

   case WM_CHAR
     SetWindowText(GetParent(hEdit), "WM_CHAR " & str(wParam))
     select case wParam

       case 1 'control-a
         SendMessage(hEdit, %EM_SETSEL, 0, -1) 'select everything
         return(0) 'do not forward Control-A

       case 48 TO 57, 45, 46  '0 to 9, minus, dot
         return(0)            'do not forward numbers, minus, dot

       case 65 TO 90          'A to Z
         'return(0)           'do not forward uppercase A to Z

       case 97 TO 122         'a to z
         'return(0)           'do not forward lowercase a to z

       case 9                 'TAB
         SetWindowText(hEdit, "tab key pressed")
         return(0)            'do not forward TAB

       case 13                'ENTER
         SetWindowText(hEdit, "enter key pressed")
         return(0)            'do not forward ENTER

       case 27                'ESC
         SendMessage(GetParent(hEdit), WM_CLOSE, 0, 0)
         return(0)

     end select

   case WM_KEYDOWN, WM_KEYUP
     SetWindowText(GetParent(hEdit), "WM_KEY " & str(wParam))
     select case wParam

       case 37 'left arrow
         SendMessage(hEdit, %EM_SETSEL, 0, 1) 'select first char
         return(0) 'rem to accept left arrow key, use up and down

       case 39 'right arrow
         SendMessage(hEdit, %EM_SETSEL, 1, 2) 'select second char
         return(0) 'rem to accept right arrow key, use up and down

     end select

 end select

 function = DefSubclassProc(hEdit, wMsg, wParam, lParam) 'forward message to edit control

end function
'____________________________________________________________________________

 WinMain()
'____________________________________________________________________________
'
  •  
    The following users thanked this post: Nicola