PlanetSquires Forums

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: XPButton issue  (Read 524 times)

Dan English

  • Junior Member
  • **
  • Posts: 63
  • FF3 User
XPButton issue
« on: November 15, 2012, 04:52:13 PM »

I'm seeing unexpected behaviour involving an XPButton control.

Picture this -- I have a parent window with an XPButton that triggers a child window.  This child window is modally opened over top of the parent.  The child window contains a big listview control.  I have the listview's double-click event coded to close the child window (and return the clicked row's lParam).

So when I double-click the child window's listview control, the child gets closed as expected.  If it so happens that the mouse cursor's x/y co-ordinate is in the same x/y co-ordinate of the parent's XPButton dimensions, the child window appears again.  Basically, the parent XPButton's BN_CLICKED message is triggered again, thus opening up the child.

This doesn't happen if I double-click the child listview over top of a normal command button on the parent.

Has anyone seem something like this, and know how I can stop the behaviour?
Logged

Paul Squires

  • Administrator
  • Guru Member
  • *****
  • Posts: 8848
  • Windows 10
    • PlanetSquires Software
Re: XPButton issue
« Reply #1 on: November 16, 2012, 08:09:49 AM »

Seems pretty odd. Maybe you can disable the button just prior to displaying your popup Form and the re-enable it once that Form closes. The XP Button is Jose's. Not sure if he is investigating the issue.
Logged
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Josť Roca

  • Guru Member
  • *****
  • Posts: 3200
Re: XPButton issue
« Reply #2 on: November 16, 2012, 11:13:55 AM »

Maybe the parent window is being re-enabled too early, or something else. (code not shown). If it fires it is because the program is sending a BN_CLICKED message to it. The part of the program that sends that message is the one to inspect.

This test works fine:

Code: [Select]
#COMPILE EXE
#DIM ALL
%UNICODE = 1

' // Include files for external files
%USEXPBUTTON = 1
#INCLUDE ONCE "CWindow.inc"        ' // CWindow class
#INCLUDE ONCE "ListViewCtrl.inc"   ' // ListView control wrapper functions

%IDC_POPUP = 1001
%IDC_LISTVIEW = 1002

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   IF AfxGetWindowsVersion => 6 THEN SetProcessDPIAware

   ' // Create an instance of the class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   ' // Note: CW_USEDEFAULT is used as the default value When passing 0's as the width and height
   pWindow.CreateWindow(%NULL, "CWindow with an XPButton", 0, 0, 500, 350, 0, 0, CODEPTR(WindowProc))

   ' // Center the window
   pWindow.CenterWindow

   ' // Add buttons
   pWindow.AddXPButton(pWindow.hwnd, %IDC_POPUP, "&Popup", 250, 250, 75, 23)
   pWindow.AddXPButton(pWindow.hwnd, %IDCANCEL, "&Close", 350, 250, 75, 23)

   ' // Default message pump (you can replace it with your own)
   pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   STATIC hInstance AS DWORD        ' // Instance handle
   STATIC lpc AS CREATESTRUCT PTR   ' // Pointer to the creation parameters
   STATIC pWindow AS IWindow        ' // Reference to the IWindow interface

   SELECT CASE uMsg

      CASE %WM_CREATE
         ' // Pointer to the creation parameters
         lpc = lParam
         ' // Instance handle
         hInstance = @lpc.hInstance
         ' // Get a reference to the IWindow interface from the CREATESTRUCT structure
         pWindow = CWindow_GetObjectFromCreateStruct(lParam)
         EXIT FUNCTION

      CASE %WM_COMMAND
         SELECT CASE LO(WORD, wParam)
            CASE %IDCANCEL
               ' // If the Escape key has been pressed...
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  ' // ... close the application by sending a WM_CLOSE message
                  SendMessage hwnd, %WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
            CASE %IDC_POPUP
               PopupDialog(pWindow)
               EXIT FUNCTION
         END SELECT

      CASE %WM_DESTROY
         ' // End the application
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Popup dialog
' ========================================================================================
SUB PopupDialog (BYVAL pParentWindow AS IWindow)

   ' // Create an instance of the class
   LOCAL pPopup AS IWindow
   pPopup = CLASS "CWindow"
   IF ISNOTHING(pPopup) THEN EXIT SUB

   ' // Create the main window
   LOCAL hwnd AS DWORD
   hwnd = pPopup.CreateWindow(pParentWindow.hwnd, "Popup dialog", 0, 0, 500, 350, _
          %WS_VISIBLE OR %WS_CAPTION OR %WS_POPUPWINDOW, %WS_EX_WINDOWEDGE, _
          CODEPTR(PopupWindowProc))

   ' // Center the window
   pPopup.CenterWindow

   ' // Add a ListView control
   LOCAL hListView AS DWORD
   hListView = pPopup.AddListView(hwnd, %IDC_LISTVIEW, "", 5, 5, pParentWindow.ClientWidth - 10, pParentWindow.ClientHeight - 10)

   ' // Add some extended styles
   LOCAL dwExStyle AS DWORD
   dwExStyle = ListView_GetExtendedListViewStyle(hListView)
   dwExStyle = dwExStyle OR %LVS_EX_FULLROWSELECT OR %LVS_EX_GRIDLINES
   ListView_SetExtendedListViewStyle(hListView, dwExStyle)

   ' // Add the header's column names
   LOCAL i AS LONG
   FOR i = 0 TO 4
      ListView_AddColumn(hListView, i, "Column" & STR$(i), 110)
   NEXT

   ' // Populate the ListView with some data
   FOR i = 0 to 29
      ListView_AddItem(hListView, i, 0, "Column 0 Row" + STR$(i))
      ListView_SetItemText(hListView, i, 1, "Column 1 Row" + STR$(i))
      ListView_SetItemText(hListView, i, 2, "Column 2 Row" + STR$(i))
      ListView_SetItemText(hListView, i, 3, "Column 3 Row" + STR$(i))
      ListView_SetItemText(hListView, i, 4, "Column 4 Row" + STR$(i))
   NEXT

   ' // Select the fist item
   ListView_SelectItem hListView, 0
   ' // Set the focus in the ListView
   SetFocus hListView

   ' // Default message pump
   pPopup.DoEvents

END SUB
' ========================================================================================

' ========================================================================================
' Editor options callback function.
' ========================================================================================
FUNCTION PopupWindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   STATIC pWindow AS IWindow           ' // Reference to the IWindow interface
   LOCAL  pnmhdr AS NMHDR PTR

   SELECT CASE uMsg

      CASE %WM_CREATE
         ' // Get a reference to the IWindow interface from the CREATESTRUCT structure
         pWindow = CWindow_GetObjectFromCreateStruct(lParam)
         ' // Disable the owner of the modal window
         EnableWindow GetWindow(hwnd, %GW_OWNER), %FALSE

      CASE %WM_COMMAND

         SELECT CASE LO(WORD, wParam)

            CASE %IDCANCEL
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  SendMessage hwnd, %WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF

         END SELECT

      CASE %WM_SIZE
         ' // Resize the ListView control and its header
         IF wParam <> %SIZE_MINIMIZED THEN
            LOCAL hListView AS DWORD
            hListView = GetDlgItem(hwnd, %IDC_LISTVIEW)
            pWindow.MoveWindow hListView, 5, 5, pWindow.ClientWidth - 10, pWindow.ClientHeight - 10, %TRUE
         END IF

      CASE %WM_NOTIFY
         pnmhdr = lParam
         SELECT CASE @pnmhdr.idFrom
            CASE %IDC_LISTVIEW
               SELECT CASE @pnmhdr.code
                  CASE %NM_DBLCLK
                     SendMessage hwnd, %WM_CLOSE, 0, 0
                     EXIT FUNCTION
               END SELECT
         END SELECT

      CASE %WM_CLOSE
         ' // The owner window is enabled in WM_CLOSE rather than WM_DESTROY to
         ' // prevent the application from losing the focus. In WM_DESTROY the
         ' // modal window has already been removed from the screen by the system.
         ' // Because the remaining windows are disabled, the system gives the
         ' // focus to another application.
         EnableWindow GetWindow(hwnd, %GW_OWNER), %TRUE

      CASE %WM_DESTROY
         ' // Close the main window
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================

Dan English

  • Junior Member
  • **
  • Posts: 63
  • FF3 User
Re: XPButton issue
« Reply #3 on: November 16, 2012, 12:31:47 PM »

Hmm, in the child window (where the double-click event is processed), I don't believe I'm doing anything crazy.  Here's my code that sets a textbox, then closes the form:

Code: [Select]
'--------------------------------------------------------------------------------
Function FORM1_CUSTOM ( _
                              hWndForm      As Dword, _  ' handle of Form
                              wMsg          As Long,  _  ' type of message
                              wParam        As Dword, _  ' first message parameter
                              lParam        As Long   _  ' second message parameter
                              ) As Long

    Local pNMLV As NM_LISTVIEW Ptr

    Select Case wMsg
        Case %WM_NOTIFY
            pNMLV = lParam       
            Select Case @pNMLV.hdr.idfrom       
                Case IDC_FORM1_LISTVIEW1        ' notify message from the listview control
                    Select Case @pNMLV.hdr.Code
                        Case %NM_DBLCLK   'left double-click
                            ' Send selected value to target control, and close selector
                            FF_TextBox_SetText(gTargetHwnd, Trim$(FF_ListView_GetItemText(HWND_FORM1_LISTVIEW1, @pNMLV.iItem, 0)))
                            FF_CloseForm hWndForm                           
                    End Select
            End Select                     
    End Select

End Function

Is there maybe a better way to deal with double-clicking a listview?
Logged

Josť Roca

  • Guru Member
  • *****
  • Posts: 3200
Re: XPButton issue
« Reply #4 on: November 16, 2012, 01:19:16 PM »

Are you using the latest version of the headers?

Dan English

  • Junior Member
  • **
  • Posts: 63
  • FF3 User
Re: XPButton issue
« Reply #5 on: November 16, 2012, 01:40:27 PM »

I'm fairly certain I've got the latest headers... all the .inc files are dated August 3, 2012 12:00 AM.
Logged

Paul Squires

  • Administrator
  • Guru Member
  • *****
  • Posts: 8848
  • Windows 10
    • PlanetSquires Software
Re: XPButton issue
« Reply #6 on: November 16, 2012, 02:32:29 PM »

I wonder if it is related to closing the Form while you are still inside the Listview double click notification.....

Maybe under %NM_DBLCLK try a PostMessage to the Form using a user defined message (catch it via the CUSTOM) handler. Try setting your textbox value and closing the Form from that handler.

Something along these lines:

Code: [Select]
%MSG_USER_CLOSEFORM = %WM_USER + 100

      Case IDC_FORM1_LISTVIEW1        ' notify message from the listview control                   
         Select Case @pNMLV.hdr.Code                       
            Case %NM_DBLCLK   'left double-click                           
                  FF_TextBox_SetText(gTargetHwnd, Trim$(FF_ListView_GetItemText(HWND_FORM1_LISTVIEW1, @pNMLV.iItem, 0)))
                 PostMessage hWndForm, %MSG_USER_CLOSEFORM, 0, 0
         End Select

Case %MSG_USER_CLOSEFORM
              FF_CloseForm hWndForm                                               
End Select
« Last Edit: November 16, 2012, 02:36:44 PM by TechSupport »
Logged
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Dan English

  • Junior Member
  • **
  • Posts: 63
  • FF3 User
Re: XPButton issue
« Reply #7 on: November 16, 2012, 02:48:26 PM »

Thanks Paul, but that doesn't seem to eliminate the issue.

I was able to implement your idea, and confirmed the necessary code path was followed, but the child form still pops up.
Logged