Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Window subclassing problem

steven_j_
Beginner
620 Views

I create an edit box as a child window control and I want to subclass it so that I can trap certain keyboard input and process it differently. I create the child edit box in my MainWndProc function in response to a WM_CREATE message. After I create it, I subclass it using the SetWindowLongPtr function. However, I immediately get a "Read access violation" error message in my new edit box procedure when it attempts to access the "message" variable. Here is the code:

!------------------------------------------------------------------------------
integer(LRESULT) function MainWndProc (hWnd, mesg, wParam, lParam)
!------------------------------------------------------------------------------
! Processes messages for the main window.
!------------------------------------------------------------------------------

---- Other specification statements ----

    integer(LONG_PTR) ebptr
    interface                                                                                 !Explicit interface to new edit box procedure
        function EditBoxProc(hwnd, mesg, wParam, lParam)
            use ifwinty
            use user32
            use TestButtonsglobals
            integer(SINT) :: EditBoxProc
            integer(HANDLE)   hwnd 
            integer(UINT)     mesg  
            integer(UINT_PTR) wParam
            integer(LONG_PTR) lParam 
        end function EditBoxProc
    end interface

----- Other statements -----

    case (WM_CREATE)

        hEdtW = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit"C, ""C, style, 416, 46, EdtRW, TxtH, hWnd, 81, ghInstance, NULL)
        ebptr = LOC(EditBoxProc)
        hOrigEditBoxProc = SetWindowLongPtr(hEdtW, GWL_WNDPROC, ebptr)  !Subclass default edit box procedure

----- Other statements -----

end function MainWndProc

!------------------------------------------------------------------------------
integer(SINT) function EditBoxProc (hWnd, mesg, wParam, lParam)   !New edit box procedure
!------------------------------------------------------------------------------
    use ifwinty
    use user32
    use TestButtonsGlobals  !Holds handle for original edit box procedure and for main window
    implicit none
    integer(HANDLE) hWnd
    integer(UINT) mesg
    integer(UINT_PTR) wParam
    integer(LONG_PTR) lParam
    integer(LRESULT) j
!
!-----Process keyboard messages.
!
    select case (mesg)          !This is where the read access violation occurs
    case (WM_KEYDOWN)
        select case (wParam)
        case (VK_TAB)
            j = SendMessage(ghwndMain, mesg, wParam, lParam)
            EditBoxProc = 1
            return
        end select
    end select
    EditBoxProc = CallWindowProc(hOrigEditBoxProc, hWnd, mesg, wParam, lParam)  !Default processing
    return
end function EditBoxProc

What am I doing wrong?

Thanks!

 

0 Kudos
7 Replies
andrew_4619
Honored Contributor II
620 Views

EditBoxProc is type INT_PTR which is either 32 or 64 bit depending on you application.

0 Kudos
steven_j_
Beginner
620 Views

Thanks for the suggestion. I tried all possible combinations (integer*4, integer*8) for ebptr (the pointer to EditBoxProc) and for the definition of EditBoxProc, and in all cases I got the same "read access violation" exception.

0 Kudos
steven_j_
Beginner
620 Views

Further clarification:

The call to SetWindowLongPtr executes successfully (the return value is non-null), and a subsequent call to GetWindowLongPtr verifies that the address of the new WndProc function for the edit box is ebptr. The read access violation occurs on some subsequent call to EdtBoxProc.

0 Kudos
IanH
Honored Contributor II
620 Views

I don't see any STDCALL attributes being applied to the procedures.

0 Kudos
andrew_4619
Honored Contributor II
620 Views
function BpatDlgProc( hDlg, message, uParam, lParam ) bind(C, name='BpatDlgProc')
        !DEC$ ATTRIBUTES STDCALL :: BpatDlgProc
        use ifwin, only: INT_PTR, HANDLE, UINT, fwparam, flparam
        implicit none
        integer(INT_PTR)                    :: BpatDlgProc
        integer(HANDLE), intent(in), VALUE  :: hDlg        ! window handle of the dialog box
        integer(UINT), intent(in), VALUE    :: message     ! type of message
        integer(fwparam), intent(in), VALUE :: uParam      ! message-specific information
        integer(flparam), intent(in), VALUE :: lParam

Callbacks usually have a template that looks like the above. As Ian says you need STDCALL attribute

0 Kudos
steven_j_
Beginner
620 Views

Andrew, Ian --

I placed the line

!DEC$ ATTRIBUTES STDCALL :: EditBoxProc

in my EditBoxProc function, and now I get a link error

Error LNK2019: unresolved external symbol _EditBoxProc@16 referenced in function _MainWndProc@16

Are there other lines I need to add? Do I need to add lines to my MainWndProc function?

Thanks!

0 Kudos
steven_j_
Beginner
620 Views

I added the line

!DEC$ ATTRIBUTES STDCALL :: EditBoxProc

to the interface block in MainWndProc, and that fixed the link problem. The program now executes correctly!

Thank you very much for your help!

0 Kudos
Reply