- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
EditBoxProc is type INT_PTR which is either 32 or 64 bit depending on you application.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't see any STDCALL attributes being applied to the procedures.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page