Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
Welcome to the Intel Community. If you get an answer you like, please mark it as an Accepted Solution to help others. Thank you!

Window subclassing problem

steven_j_
Beginner
246 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 I
246 Views

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

steven_j_
Beginner
246 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.

steven_j_
Beginner
246 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.

IanH
Black Belt
246 Views

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

andrew_4619
Honored Contributor I
246 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

steven_j_
Beginner
246 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!

steven_j_
Beginner
246 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!

Reply