Loading OCX dynamically in VB 6.0 - winapi

I am loading OCX dynamically in VB 6.0.
The following is the code that I am using to load and call the methods:
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Any, ByVal wParam As Any, ByVal lParam As Any) As Long
Private Sub Foo
On Error Resume Next
Dim lb As Long, pa As Long
Dim versionString As String
Dim retValue as Long
lb = LoadLibrary("D:\projects\other\VB_DLLs\TestDLL\TestDLL.dll")
'retrieve the address of getVersion'
pa = GetProcAddress(lb, "getVersion")
'Call the getVersion function'
retValue = CallWindowProc (pa, Me.hWnd, "I want my version", ByVal 0&, ByVal 0&)
'release the library'
FreeLibrary lb
End Sub
Now I want to access public properties of OCX. How I can access (get/set) the properties of OCX?

You can not use an OCX/COM control in that manner.
To create and use an instance of the object, you will need to.. create an instance of the object, then use that.
Set TestObject = CreateObject("TestDll.TestObject")
Value = TestObject.Method(InputValue)
This requires the DLL to be registered, and will use whichever is registered rather than a specific instance.
If you don't want it to be registered, look at DirectCOM.

Related

How to find a window by FindWindowW from the unicode window title text?

I have tried to use GetWindowTextW to extract the window title text successfully, and it is a unicode text. When I use FindWindowW to find the window, it failed and the returned Hwnd is 0.
The window with the unicode title:
The code on VB6 is below. the currentHwnd is the window Hwnd I captured already and it works well during my test:
Private Declare Function FindWindowW Lib "user32" (ByVal lpClassName As Long, ByVal lpWindowName As Long) As Long
Private Declare Function GetWindowTextW Lib "user32" (ByVal hWnd As Long, ByVal lpString As Long, ByVal cch As Long) As Long
Private Declare Function GetWindowTextLengthW Lib "user32" (ByVal hWnd As Long) As Long
Private Sub cmdOK_Click()
Dim titleString As String
dim newHwnd as Long
dim Class as string
Class = Space(500)
GetClassName currentHwnd, Class, Len(Class)
titleString = String$(256, 0)
GetWindowTextW currentHwnd, StrPtr(titleString), GetWindowTextLengthW(currentHwnd)
newHwnd = FindWindowW(StrPtr(Class), StrPtr(titleString))
End Sub

Performing a KeyDown function without focus in Visual Basic

It's quite simple really. I want for an application to keep monitoring KeyDown events even without focus.
Private Sub Form1_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyData
Case Keys.MediaStop
PictureBox2_Click(sender, e)
Case Keys.MediaPlayPause
PauseToolStripMenuItem_Click(sender, e)
Case Keys.MediaNextTrack
SkipTrackToolStripMenuItem_Click(sender, e)
Case Keys.MediaPreviousTrack
PreviousTrackToolStripMenuItem_Click(sender, e)
End Select
End Sub
The above code is for a music player. Functions are called when the media keys are pressed ('Fn'+ 'Home', 'Fn' + 'Pg Up'...etc)
In a previous comment, somebody suggested looking into WH_KEYBOARD_LL for a solution but I didn't really understand much of it, if I'm honest.
UPDATE:
The link suggested isn't great as the 'As Any' keyword is not supported in 'Declare' functions.
This is how far I've got with it...
Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As **Any**) As Long
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Declare Function SetWindowsHook Lib "user32" Alias "SetWindowsHookA" (ByVal nFilterType As Long, ByVal pfnFilterProc As Long) As Long
Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As **Any**, Source As **Any**, ByVal Length As Long)
**Global** Const WH_KEYBOARD_LL = 13
Public Const HC_ACTION = 0
Structure HookStruct
Dim vkCode As Long
Dim scancode As Long
Dim flags As Long
Dim time As Long
Dim dwExtraInfo As Long
End Structure
The errors that Visual Studio is underlining are all written in bold
On hover of 'Any' it gives me the message "'As Any' is not supported in 'Declare' statements"
On hover of 'Global' it gives "Syntax error"
Implementing Keyboard hook using Windows API is the solution. Please check : http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=13506&lngWId=1
If you are using VB6 and want to Hide the Navigation Bar, simply do this.
aw$ = "^(h)"
SendKeys aw$
Apply this after pdf file loads.

sendmessage not working for jetaudio in vb6

i am trying to implement the Jetaudio API in vb6...
i have taken the values of the constants from the API SDK..
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function RegisterWindowMessage _
Lib "user32" Alias "RegisterWindowMessageA" _
(ByVal lpString As String) As Long
Public Const WM_APP As Long = &H8000
Public Const MyMSG As Long = WM_APP + 740
Public Function GetJetAudioSong()
Dim v As Long
Dim JAhwnd As Long
Dim lngMyMsg As Long
lngMyMsg = RegisterWindowMessage(MyMSG)
JAhwnd = FindWindow("COWON Jet-Audio Remocon Class", "Jet-Audio Remote Control")
v = SendMessage(JAhwnd, lngMyMsg, 0, 995)
MsgBox v
End Function
Now, FindWindow() is working cause JAhwnd is set with a value...
its just the sendmessage() that doesn't seem to be working...
the code is suppose to msgbox the version number for the running Jet Audio instance.
i've been at it for days now and i have no way of making sure weather this error is a VB thing or not... i am taking Jet Audio's SDK's word that the values of the const are correct...
the value of v is always 0 where it should be 6 on my system.
what am i doing wrong?
Don't call RegisterWindowMessage, MyMSG is message number that you should send to the Jet-Audio window.
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Const WM_APP As Long = &H8000
Public Const MyMSG As Long = WM_APP + 740
Public Function GetJetAudioSong()
Dim v As Long
Dim JAhwnd As Long
Dim lngMyMsg As Long
JAhwnd = FindWindow("COWON Jet-Audio Remocon Class", "Jet-Audio Remote Control")
v = SendMessage(JAhwnd, MyMSG, 0, 995)
MsgBox v
End Function
What Windows Version?
SendMessage and SendKeys no longer works with VB6 code starting at Windows Vista and above.
Do a Google search for it.
I know this is 2 years too late. Please use this as a future reference for anyone reading this in the future.
The fix for your issue is this:
'[ Use 'ByVal' for your lParam to make sure you are passing the actual value not the Reference
v = SendMessage(JAhwnd, lngMyMsg, 0, ByVal 995)
'[ Or you could perform PostMessage(..) and not use ByVal
v = PostMessage(JAhwnd, lngMyMsg, 0, 995)
Also, i HIGHLY recommend against anyone using SendKeys. API is the correct method to ensure you are sending message to the correct hWnd. I would suggest using SendKeys only if in desperation; it can happen.

Accessing dynamically loaded DLL (with LoadLibrary) in Visual Basic 6

I have a need to create a wrapper for a DLL, loading and unloading it as needed (for those interested in the background of this question, see How to work around memory-leaking 3rd party DLL (no source code) accessed by Tomcat application?) . I'm doing it in Visual Basic 6, and the loading and unloading with the following example works:
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Sub cmdTestLoadingDLL_Click()
Dim lb As Long, pa As Long
lb = LoadLibrary("D:\projects\other\VB_DLLs\TestDLL\TestDLL.dll")
Msgbox "Library address: " + lb
FreeLibrary lb
End Sub
I can see using Process Explorer that the DLL is loaded to memory when the messagebox is displayed, and is discarded afterwards. However, calling the method is naturally not enough - I need to access the methods within the dynamically loaded DLL.
How can I achieve this? I would like to call the method getVersion in class mainClass, which is in TestDLL, like this:
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Sub cmdTestLoadingDLL_Click()
Dim lb As Long, pa As Long
Dim versionString As String
lb = LoadLibrary("D:\projects\other\VB_DLLs\TestDLL\TestDLL.dll")
versionString = "- From DLL: " + mainClass.getVersion
MsgBox versionString
FreeLibrary lb
End Sub
However, the line
versionString = "- From DLL: " + mainClass.getVersion
throws an error "Object required".
First of all, since you are calling it via LoadLibrary, there are no classes here - only functions are exported for public consumption. So your mainClass reference would never work. Let's assume you have a function getVersion that is exported.
I would try the following:
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Any, ByVal wParam As Any, ByVal lParam As Any) As Long
Private Sub Foo
On Error Resume Next
Dim lb As Long, pa As Long
Dim versionString As String
Dim retValue as Long
lb = LoadLibrary("D:\projects\other\VB_DLLs\TestDLL\TestDLL.dll")
'retrieve the address of getVersion'
pa = GetProcAddress(lb, "getVersion")
'Call the getVersion function'
retValue = CallWindowProc (pa, Me.hWnd, "I want my version", ByVal 0&, ByVal 0&)
'release the library'
FreeLibrary lb
End Sub
Do you need to call COM methods on this DLL? If so, I'm not at all sure this is possible.
Matthew Curland's excellent Advanced Visual Basic 6 is the first place I'd look, though. There's some powerful under-the-hood COM stuff in there that circumvents the normal VB6 techniques.
There's also DirectCom, which allows you to call COM methods without using COM. Never used it myself, but people chat about it on the VB6 newsgroup.

How to download multiple files in VB6 with progress bar?

I want to download multiple files (mostly images) from VB6 application. presently i m using URLDownloadToFile but it allows only one file at a time and there is no progress bar. I want to download multiple files and with progress bar. please help. thanks in advance.
my present code:
Dim lngRetVal As Long
lngRetVal = URLDownloadToFile(0, URL, LocalFilename, 0, 0)
If lngRetVal = 0 Then DownloadFile = True
You want to download the file asynchronously, so that your VB code continues executing while the download happens. There is a little-known way to do this with native VB6, using the AsyncRead method of UserControl and UserDocument objects - no need for API calls.
Here's an excellent explanation and VB6 code for multiple simultaneous downloads, from the renowned VB6 guru Karl Peterson. The AsyncReadProgress event gives you the BytesRead and BytesMax, which will allow you to display a progress bar.
You're hoping for a VB answer, but this is non trivial.
Most of the following comes from http://www.experts-exchange.com/Programming/Languages/Visual_Basic/Q_20571958.html
IBindStatusCallback interface is not
directly accessible from VB. It must
be introduced into a compatible type
library.
You can find the Type library
olelib.tlb under:
http://www.domaindlx.com/e_morcillo/scripts/type/default.asp
The zip file name to download is:
tl_ole.zip
You will also find examples on how to
use it included. Not sure thou whether
you will find a specific example on
IBindStatusCallback on not, but it
worth giving it a try.
You can write your own function to get the data into a string, which will give you full control over everything:
Option Explicit
Public Const INTERNET_OPEN_TYPE_PRECONFIG = 0
Public Const INTERNET_DEFAULT_HTTP_PORT = 80
Public Const INTERNET_SERVICE_HTTP = 3
Public Const INTERNET_FLAG_RELOAD = &H80000000
Public Const HTTP_QUERY_STATUS_CODE = 19
Public Const HTTP_ADDREQ_FLAG_ADD = &H20000000
Public Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
Public Declare Function InternetConnect Lib "wininet.dll" Alias "InternetConnectA" (ByVal hInternetSession As Long, ByVal sServerName As String, ByVal nServerPort As Integer, ByVal sUsername As String, ByVal sPassword As String, ByVal lService As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
Public Declare Function HttpOpenRequest Lib "wininet.dll" Alias "HttpOpenRequestA" (ByVal hHttpSession As Long, ByVal sVerb As String, ByVal sObjectName As String, ByVal sVersion As String, ByVal sReferer As String, ByVal something As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
Public Declare Function HttpSendRequest Lib "wininet.dll" Alias "HttpSendRequestA" (ByVal hHttpRequest As Long, ByVal sHeaders As String, ByVal lHeadersLength As Long, ByVal sOptional As String, ByVal lOptionalLength As Long) As Long
Public Declare Function HttpQueryInfo Lib "wininet.dll" Alias "HttpQueryInfoA" (ByVal hHttpRequest As Long, ByVal lInfoLevel As Long, ByRef sBuffer As Any, ByRef lBufferLength As Long, ByRef lIndex As Long) As Long
Public Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer
Public Declare Function HttpAddRequestHeaders Lib "wininet.dll" Alias "HttpAddRequestHeadersA" (ByVal hHttpRequest As Long, ByVal sHeaders As String, ByVal lHeadersLength As Long, ByVal lModifiers As Long) As Integer
Public Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As String, ByVal lNumberOfBytesToRead As Long, lNumberOfBytesRead As Long) As Integer
Public Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" (ByVal hInternet&, ByVal lpszUrl As String, ByVal lpszHeaders As String, ByVal dwHeadersLength&, ByVal dwFlags&, ByVal dwContext&) As Long
Public Declare Function InternetQueryDataAvailable Lib "wininet.dll" (ByVal hFile As Long, lpdwNumberOfBytesAvailable As Long, ByVal dwFlags As Long, ByVal dwContext As Long) As Long
Public Function GetHTML(strURL As String) As String
Const BufferSize = 16384
Dim hSession&, hURL&, lRet&, lBytesAvail&
Dim Buffer As String * BufferSize
Dim BufferLen&, sResult$
hSession = InternetOpen(vbNullString, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
hURL = InternetOpenUrl(hSession, strURL, vbNullString, ByVal 0&, INTERNET_FLAG_RELOAD, ByVal 0&)
sResult = ""
Do
InternetReadFile hURL, Buffer, Len(Buffer), BufferLen
If BufferLen > 0 Then sResult = sResult & Left(Buffer, BufferLen)
Loop Until BufferLen = 0
GetHTML = sResult
InternetCloseHandle hURL
InternetCloseHandle hSession
End Function
You will find additional resources for doing the callback method here (scroll down to the bottom):
http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_21763861.html
http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_21746456.html
But I honestly think you'll be better off making your own download function if you want more control over it. TCP/IP stuff in VB is actually very easy.
-Adam

Resources