Announcement

Collapse

Maintenance

The forum could be offline for 30-60 minutes in the very near future for maintenance (said 3pm Pacific). I was behind on getting this notice. I do apologize.
See more
See less

Button warning..

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • George Bleck
    replied
    (My $.02)

    I am an old DOS programmer and feel more comfortable using the keys then the mouse at times.

    From experience, I NEVER use the enter key as it would trigger the default button, rather, I use the spacebar to activate the focused key.

    ------------------
    George W. Bleck
    Senior System Engineer
    KeySpan Corporation

    Leave a comment:


  • Borje Hagsten
    replied
    Theory is correct, yes - but %BN_CLICKED = 0, so Esc still works.
    Reason for testing BN_CLICKED is so button isn't triggered on wrong
    notification.

    ------------------
    Forgot to add: If a button has BS_NOTIFY style, it can cause highly
    unpredictable results if not BN_CLICKED is tested. Not sure for regular
    button, but think things like CONTROL DISABLE (EnableWindow) triggers
    notification. To be on safe side - always test BN_CLICKED.


    [This message has been edited by Borje Hagsten (edited September 12, 2001).]

    Leave a comment:


  • Dominic Mitchell
    replied
    Borje;
    In standard sdk style GUI programming the tab and arrows keys work as expected.
    However, keyboard handling in Microsoft Windows, as noted by some authors,
    seems to have been an afterthought. When one tries to change the keyboard focus
    programmatically in a window that contain a pushbutton with an id of IDOK
    things go awry. There are also related visual problems with the BS_PUSHBUTTON/
    BS_DEFPUSHBUTTON styles.
    In other words the problem is that call to SetFocus in WM_COMMAND.
    SetFocus and IsDialogMessage ain't that great a couple.
    To return the focus to the first control do the following-
    Code:
      SELECT CASE wMsg
         CASE %WM_COMMAND
            IF HIWRD(wParam) = %BN_CLICKED THEN
               SELECT CASE LOWRD(wParam)
                  CASE %IDOK     : MSGBOX "IDOK"
                  CASE %IDCANCEL : MSGBOX "%IDCANCEL"
               END SELECT
               PostMessage hWnd, %WM_KEYDOWN, %VK_TAB, 0  
            END IF
    The following is off topic but may be useful to lurkers.
    Your WM_COMMAND filter as it stands does not handle the default behaviour
    of windows with IsDialogMessage() in the message loop. The test

    IF HIWRD(wParam) = %BN_CLICKED THEN

    prevents the following cases from being trapped
    (they all generate IDCANCEL but with HIWRD(wParam) = 0)-
    1. User closing the window via the system menu.
    2. User closing the window via the x button in the title bar.
    3. User closing the window by pressing the Escape key.

    I would rewrite the code as follows(no need for WM_SYSCOMMAND)-
    1. filter on control ids(usually unique numeric values set by programmer)
    2. filter on notifications(numeric values may not be unique and are set by MS)
    Code:
      CASE %WM_COMMAND
        SELECT CASE LOWRD(wParam)
          CASE %IDC_APPLY
            IF HIWRD(wParam) = %BN_CLICKED THEN
              MSGBOX "APPLY"
            END IF
    
          CASE %IDOK
            MSGBOX "IDOK"
    
          CASE %IDCANCEL
            MSGBOX "%IDCANCEL"
        END SELECT
    [This message has been edited by Dominic Mitchell (edited September 12, 2001).]

    Leave a comment:


  • Borje Hagsten
    replied
    Just wanted to tell, since it can give dangerous result. Like I said,
    imagine question was "Format drive C?", etc. Using other id's, also
    strange result, but not as dangerous. Then if dialog gives button focus
    (ie, first control in tab order), Right arrow + Enter works/works not,
    every other time. No danger if it sometimes doesn't work, but..

    Personally, think I'll avoid using MS buttons in "commercial" code from here on..


    ------------------

    Leave a comment:


  • Lance Edmonds
    replied
    I concur.

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Leave a comment:


  • Semen Matusovski
    replied
    In both cases results depends of IsDialogMessage.
    I avoid %IDOK, %IDCANCEL as button's id.s to have a possibility to recognize real "click".

    ------------------
    E-MAIL: [email protected]

    Leave a comment:


  • Borje Hagsten
    replied
    Had to test. Same problem in SDK, so a Redmond-based problem. Even
    stranger - it seems it only happens every other time. SDK test:
    Code:
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Simple SDK-style template
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    #COMPILE EXE
    #INCLUDE "WIN32API.INC"
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main entrance
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION WINMAIN (BYVAL hInst AS LONG, BYVAL hPrevInstance AS LONG, _
                      lpCmdLine   AS ASCIIZ PTR, BYVAL iCmdShow AS LONG) AS LONG
     
      LOCAL hWnd AS LONG, hBtn1 AS LONG, hBtn2 AS LONG, style AS LONG
      LOCAL Msg        AS tagMsg
      LOCAL szAppName  AS ASCIIZ * 50
      LOCAL wndclass   AS WndClassEx
      LOCAL rc         AS RECT
     
      szAppName              = "MYPROG"
      wndclass.cbSize        = SIZEOF(WndClass)
      wndclass.style         = %CS_HREDRAW OR %CS_VREDRAW
      wndclass.lpfnWndProc   = CODEPTR( WndProc )
      wndclass.hInstance     = hInst
      wndclass.hCursor       = LoadCursor( %NULL, BYVAL %IDC_ARROW )
      wndclass.hbrBackground = GetStockObject(%LTGRAY_BRUSH)
      wndclass.lpszClassName = VARPTR( szAppName )
     
      IF registerClassEx(wndclass) = 0 THEN EXIT FUNCTION 'what else to do..?
     
      SystemParametersInfo %SPI_GETWORKAREA, BYVAL 0, VARPTR(rc), 0 'for centering on screen
     
      'Create a window using the registered class
      hWnd = CreateWindow(szAppName, _                           ' window class name
                          "Press Right arrow, then Enter - repeat", _ ' window caption
                          %WS_CAPTION OR %WS_SYSMENU, _          ' window style
                          ((rc.nRight - rc.nLeft) - 300) / 2, _  ' initial x position
                          ((rc.nBottom - rc.nTop) - 200) / 2, _  ' initial y position
                          300, _                                 ' initial x size
                          200,_                                  ' initial y size
                          %NULL, _                               ' parent window handle
                          %NULL, _                               ' window menu handle
                          hInst, _                               ' program instance handle
                          BYVAL %NULL)                           ' creation parameters
     
      style = %WS_CHILD + %WS_VISIBLE + %WS_TABSTOP
      hBtn1 = CreateWindow("BUTTON", "&OK", style, 70, 140, 80, 22, hwnd, %IDOK, hInst, %NULL)
      hBtn2 = CreateWindow("BUTTON", "E&xit", style, 150, 140, 80, 22, hwnd, %IDCANCEL, hInst, %NULL)
      SetFocus hBtn1
     
      'Display the window on the screen
      ShowWindow hWnd, iCmdShow : UpdateWindow hWnd
     
      'Main message loop:
       While GetMessage(Msg, %NULL, 0, 0)
          If IsDialogMessage (hWnd, Msg) Then
          Else
             TranslateMessage Msg
             DispatchMessage  Msg
          End If
       Wend
     
      FUNCTION = msg.wParam
    END FUNCTION
     
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    ' Main dialog procedure
    '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                      BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG
     
      SELECT CASE wMsg
         CASE %WM_COMMAND
            IF HIWRD(wParam) = %BN_CLICKED THEN
               SELECT CASE LOWRD(wParam)  'GetDlgCtrlID(GetFocus)  'fixes problem!
                  CASE %IDOK     : MSGBOX "IDOK"
                  CASE %IDCANCEL : MSGBOX "%IDCANCEL"
               END SELECT
               SetFocus GetDlgItem(hWnd, %IDOK) 'return focus to first control, IDOK
            END IF
     
         CASE %WM_DESTROY
            PostQuitMessage 0
            FUNCTION = 0 : EXIT FUNCTION
     
      END SELECT
      FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
    END FUNCTION

    ------------------

    Leave a comment:


  • Michael Mattias
    replied
    Don't know what MS have been thinking
    Call me a naif, but if CBCTL does not return the same value as GetDlgCtrlID(GetFocus), and lParam is not available under DDT, and using the API call rather than the DDT function produces the correct value, wouldn't that mean the problem is located several hundred miles south of Redmond WA?

    I mean, I use SDK-style programming all the time, where LOWRD(wParam) is the control ID, and I've never gotten the wrong control on a button click.

    MCM

    Leave a comment:


  • Borje Hagsten
    started a topic Button warning..

    Button warning..

    A very sad day for the civilized world, but still we must try to go on..

    Writing own button has thaught me a lot about standard ones. Found a bit
    dangerous thing about standard buttons that may be good to know: If you
    use the arrow keys to move between them and press Enter when a button has
    focus, you may trigger wrong button!

    Don't know what MS have been thinking. If to use Tab key, no problems. Right
    button will be triggered. The sample code below shows. Compile and start,
    then press Right arrow to give Cancel button focus and press Enter. MSGBOX
    will tell Cancel button was triggered. Okay, but repeat: when Msgbox is
    closed, OK button will get focus again. Press Right arrow once more to
    give Cancel focus and press Enter. MSGBOX tells OK button has been triggered!!!
    Imagine question was "Format drive C?" ..

    Simple fix: Don't look for CBCTL (LOWRD(wParam)) in WM_COMMAND. Instead use
    GetDlgCtrlID(GetFocus). See sample below and test the different ways. Just
    tell it, so you know that just because an MS button has focus, it doesn't
    mean it will be triggered if user presses Enter..
    Code:
    #COMPILE EXE
    #INCLUDE "WIN32API.INC"
    DECLARE CALLBACK FUNCTION DlgMainProc
     
    '********************************************************************
    ' Main entrance - create dialog and controls
    '********************************************************************
    FUNCTION WINMAIN (BYVAL hInst AS LONG, BYVAL hPrevInstance AS LONG, _
                      lpszCmdLine AS ASCIIZ PTR, BYVAL nCmdShow AS LONG) AS LONG
     
      LOCAL hDlg AS LONG
      DIALOG NEW 0, "Press Right arrow, then Enter - repeat",,, 200, 100, %WS_SYSMENU TO hDlg
     
      CONTROL ADD BUTTON, hDlg, %IDOK, "ID&OK",           4, 4, 50, 14
      CONTROL ADD BUTTON, hDlg, %IDCANCEL, "ID&CANCEL",  54, 4, 50, 14
     
      DIALOG SHOW MODAL hDlg, CALL DlgMainProc
    END FUNCTION
     
    '********************************************************************
    ' Main message handling procedure
    '********************************************************************
    CALLBACK FUNCTION DlgMainProc
      SELECT CASE CBMSG
         CASE %WM_COMMAND
            IF CBCTLMSG = %BN_CLICKED THEN
               SELECT CASE CBCTL  'CASE GetDlgCtrlID(GetFocus)  fixes problem!
                  CASE %IDCANCEL : Msgbox "%IDCANCEL"
                  CASE %IDOK     : Msgbox "%IDOK"
               END SELECT
            END IF
      END SELECT
    END FUNCTION

    ------------------
Working...
X