|
-
Oct 2nd, 2002, 04:32 AM
#1
When Subclassing what is an error 5?
I have this:
VB Code:
SetLastError 0
.oldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WndProc)
MsgBox GetLastError
I have no idea why it doesn't work, but the error returned is number 5?! *sigh*
Anyone got any tips?
-
Oct 2nd, 2002, 04:53 AM
#2
Frenzied Member
Purpose
When using the API, Visual basic does not throw exceptions in the usual manner. Instead it is up to the programmer to check the value of the intrinsic Err.LastDLLError after each call to the API to see if an error has occured.
However, this number should be converted into a string message to make it easier to understand what went wrong.
VB Code:
'\ API Error decoding
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long
'\ -- [ LastSystemError ]----------------------------------
'\ Returns the message from the system which describes the
'\ last dll error to occur, as
'\ held in Err.LastDllError. This function should be
'\ called as soon after the API call
'\ which might have errored, as this member can be reset
'\ to zero by subsequent API calls.
'\ --------------------------------------------------------
Public Function LastSystemError() As String
Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
Dim sError As String * 500 '\ Preinitilise a string buffer to put any error message into
Dim lErrNum As Long
Dim lErrMsg As Long
lErrNum = Err.LastDllError
lErrMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, ByVal 0&, lErrNum, 0, sError, Len(sError), 0)
LastSystemError = Trim(sError)
End Function
-
Oct 2nd, 2002, 04:57 AM
#3
Yea, I did try that, cut and paste code from AllAPI.Net, but the format command crashed my app 
Yours seems to work for some reason...
My error is "Access Denied"...WHY?! Trying to subclass a window in from one project, in another...Access Denied???!!! 
You're a subclassing API expert...any clue?
Woka
-
Oct 2nd, 2002, 05:05 AM
#4
Frenzied Member
You can't subclass a window that is in a different process than you are in.
Every process has it's own reserved memory and it addresses that memory using local pointers - kinda like door numbers in a street. These addresses are meaningless outside of the current process so if you pass one to another process and say "use this as your windproc" it will look at that address relative to it's memory and fail to find a Wndproc there.
The only way to subclass somebody else's program is to make that program load a dll that has your subclassing code in it and then (because the dll will be loaded in it's address space) you can use SetWindowLong as normal.
However the phrase make that program load a dll that has your subclassing code in it hides a world of grey hair and blue screens of death.
-
Oct 2nd, 2002, 05:06 AM
#5
Fanatic Member
The window you're trying to subclass - do you own it? if you dont.....then you cant.
Crispin
VB6 ENT SP5
VB.NET
W2K ADV SVR SP3
WWW.BLOCKSOFT.CO.UK
[Microsoft Basic: 1976-2001, RIP]
-
Oct 2nd, 2002, 05:14 AM
#6
Right OK, undertand now. It would have worked if I had used a DLL instead of EXE...d'oh! 
Ok, since I know the parent windows handle in the activeX EXE, from the client when the picture box resizes, I can just call a Refresh function in the object, and that can use API, to get rect size and move window...anyway, that way work...not exactally what I wanted but hey, beggers can't be choosers 
Cheers for your help...
Woka
-
Oct 2nd, 2002, 05:18 AM
#7
Frenzied Member
If you wrote both ActiveX exes you can communicate between them by posting registered messages as per this article
-
Oct 2nd, 2002, 05:27 AM
#8
Yea, that was my next move...So I could theorectically have a WM that looked like:
NEW_SEARCH SELECT * FROM TABLE ORDER BY PK_ID
Then when I trap is I check to see if NEW_SEARCH is at the start of the message, and if it is then I strip out the select statement and execute it...?
Is that correct?
Woka
Cheers for the help
-
Oct 2nd, 2002, 05:35 AM
#9
Frenzied Member
How I would do this:
Application 1 uses RegisterWindowsMessage to register a new message "NEW_SEARCH"
Application 2 registers a new message called "NEW_SEARCH_RESPONSE"
When a new search is performed application #1 uses GlobalAddAtom to add the string to the global atom table and stores it's atom handle in a variable.
Application #1 sends application#2 a "NEW_SEARCH" message with it's reply to hwnd in the lParam and the global atom identifier in the wParam.
Application #2 gets that message and reads the search parameter with GlobalGetAtom and sends back a "NEW_SERACH_RESPONSE" message with that same atom id in the wParam
Application #1 removes the atom from the atom table
This way you don't have to worry about allocating memory that both processes can read and controlling access to it etc.
HTH,
Duncan
-
Oct 2nd, 2002, 05:50 AM
#10
Think I undertsnad that...
-
Oct 2nd, 2002, 06:18 AM
#11
Frenzied Member
In a module shared by both projects add the following code:
VB Code:
Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long
Public Function WM_NEW_SEARCH() As Long
WM_NEW_SEARCH = RegisterWindowMessage("NEW_SEARCH")
End Function
Public Function WM_NEW_SEARCH_RESPONSE() As Long
WM_NEW_SEARCH = RegisterWindowMessage("NEW_SEARCH_RESPONSE")
End Function
Then in the application that does the searching stuff (hereafter the app#1):
VB Code:
Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal lpString As String) As Integer
Declare Function GlobalDeleteAtom Lib "kernel32" Alias "GlobalDeleteAtom" (ByVal nAtom As Integer) As Integer
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Function myWndProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If msg = WM_NEW_SEARCH_RESPONSE() Then
'\\ We got a response back - delete the global atom
Call GlobalDeleteAtom(wParam)
Else
'\\ Pass this message on to the previous wndproc
myWndProc = CallWindowproc(mlpPrevWndProc, hwnd,wMsg,wParam, lParam)
End If
End Function
Public Sub NewSearch(ByVal SearchString As String)
Dim hAtom As Integer
hAtom = GlobalAddAtom(SearchString)
'\\ Post this to our other application
Call PostMessage(hwndClient , WM_NEW_SEARCH(), hAtom, hwndReturn)
End Sub
And in APP#2
VB Code:
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function GlobalGetAtomName Lib "kernel32" Alias "GlobalGetAtomNameA" (ByVal nAtom As Integer, ByVal lpBuffer As String, ByVal nSize As Long) As Long
Public Function myWndProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim sSearch As String, lRet As Long
If msg = WM_NEW_SEARCH() Then
'\\ We got a new search..
'\\ 1 - read the global atom
sSearch = String$(255,0)
lRet = GlobalGetAtomName(wParam, sSearch, Len(sSearch))
If lRet > 0 Then
sSearch = Left$(sSearch)
'\\ Do whatever action with the search strinmg here....
End If
'\\ 2 - Acknowledge it's reciept...
Call PostMessage(lParam, WM_NEW_SEARCH_RESPONSE() ,wParam, 0)
Else
'\\ Pass this message on to the previous wndproc
myWndProc = CallWindowproc(mlpPrevWndProc, hwnd,wMsg,wParam, lParam)
End If
End Function
You need to use FindWindow to get the hwndClient which is the window handle subclassed in app#2, and hwndReturn is the window handle of the window subclassed by myWndProc in app#1
Hope this helps,
Duncan
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|