SAPI5 Event returns 42 instead of 0 - windows

I am using SAPI5 COM, and there is one event called
Word(ByVal StreamNumber As Long, ByVal StreamPosition As Variant, ByVal CharacterPosition As Long, ByVal Length As Long)
It works fine, but CharacterPosition starts off with 42, and I have no idea why it doesn't start off with 0 or 1.
The docu say:
CharacterPosition
The character position in the input stream one character before the start of the word. In the case of the first word in a stream, this parameter is zero.
But for me, it always starts with 42, no matter which voice I use.
Does anybody know what might cause this?
Thank you very much!

I found the reason:
The stupid SAPI5 engine takes the tags into account.

Related

What is happening in this code

I was looking for some vb6 that would allow me to populate a listbox with a directory of files when I found the following elegant piece of code.
List1.hwnd, &H18D, &H20, "directory*.*"
Most of the other examples I found were 4 or more lines of code. Can someone help me understand what is happening here? What is the
List1.hwnd, &H18D, &H20
Part doing?
There was a general declaration I left out.
Private Declare Function SendMessageStr Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Your edit still makes not enough sense - unless the code was
SendMessageStr List1.hwnd, &H18D, &H20, "directory*.*"
and you thought the space means it's a stand-alone bit (it isn't).
That code is
SendMessage (List1.hwnd, LB_DIR, DDL_ARCHIVE, "directory*.*") - it sends a documented Windows message to a ListBox control named List1 to fill it with files that match the mask "directory*.*", including the archived ones.

Is there an API to get the advanced printer device settings?

I need to get the available supported printer document features for a particular printer through the win32 api.
The options I'm referring to are displayed for a sample printer in the image below. You can get this dialog by right clicking the printer icon and the click preferences, and the clicking the advanced tab in the dialog.
Can anyone tell me the need api i need to call, and in what other?
I am targeting Windows Windows XP+ and using vb6.
The DeviceCapabilities function is read only. What you're looking for is the DocumentProperties function. DeviceCapabilities is actually rather dated and should have been obsoleted long ago since it assumes only a single user and single application is using the printer. You don't want to set printer properties for every print job; you want to set document properties for your current print job. The DocumentProperties function will do that for you, but pay close attention to the instructions in the link above on how to make changes. It's a needlessly complex function.
What I think you are looking for is DeviceCapabilities from winspool.drv. Sample code from Microsoft. Most of the documentation online now days is for .Net, So I typed in the VB6 definition from Dan Appleman's Visual Basic Programmer's Guide to the Win32 API
The declaration for VB6 is:
Declare Function DeviceCapabilities& Lib "winspool.drv" Alias "DeviceCapabilitiesA" (ByVal lpDeviceName as String, ByVal lpPort as String, ByVal iIndex as Long, ByVal lpOutput as String, ByVal lpDeviceMode as Long)
Based on your Comment you would need to use DocumentProperties it can be used to retreive or modify a DevMode Structure. It may or may not have what you are looking for. Your best bet would be to get the above book, Chapter 12 has wealth of information. Also looking at your picture it looks like you are using somesort of a POS print, you should consult the manufacturers documentation about specific api's that the printer might support.
Declare Function DocumentProperties& Lib "winspool.drv" Alias "DocumentPropertiesA" (ByVal hwnd as Long, ByVal hPrinter as Long, ByVal pDeviceName as String, ByVal pDeviceModeOutput as Long, ByVal pDeviceModelInput as Long, ByVal fMode as Long)
DevMode Structure
Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32
Type DEVMODE
dmDeviceName as String * CCHDEVICENAME
dmSpecVersion as Integer
dmDriverVersion as Integer
dmSize as Integer
dmDriverExtra as Integer
dmFields as Long
dmOrientation as Integer
dmPaperSize as Integer
dmPaperLength as Integer
dmPaperWidth as Integer
dmScale as Integer
dmCopies as Integer
dmDefaultSource as Integer
dmPrintQuality as Integer
dmColor as Integer
dmDuplex as Integer
dmYResolution as Integer
dmTTOption as Integer
dmCollate as Integer
dmFormName as String * CCHFORMNAME
dpBitsPerPixel as Integer
dmBitsPerPel as Long
dmPelWidth as Long
dmPelHeight as Long
dmDisplayFlags as Long
dmDisplayFrequency as Long
dmICMMethod as Long
dmICMIntent as Long
dmMediaType as Long
dmDitherType as Long
dmReserved1 as Long
dmReserved2 as Long
End Type

Using vbAccelarator Win32 Hook crashes application along with VB IDE

I'm working on VB6 project where I need to have keyboard short-cuts for Buttons on Toolbar Control. To accomplish this, I have used Win32 Hooks library from vbAccelerator. Here's my IWindowsHook_HookProc function, that I use to retrieve Key strokes & perform action based on pressed short-cut (Ctrl + N for New, Ctrl + O for Open and Ctrl + S for Save) , but the I don't know what's wrong with the code that crashes my application along with VB6 IDE. The function is currently incomplete as I just tried to identify Ctrl + N key combination to test this feature. Please help me out.... :-|
Private Function IWindowsHook_HookProc(ByVal eType As EHTHookTypeConstants, ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long, bConsume As Boolean) As Long
If KeyboardlParam(lParam).KeyDown Then
Select Case True
Case Me.ActiveControl = Me
If wParam = vbKeyControl + vbKeyN Then
frmNewReport.show
bConsume = True
End If
End Select
End If
Using a hook in the IDE can lead to lots of crashes, heck using a hook without fully understanding what you are doing is going to lead to a lot of crashes period...
Mark is correct about the Timer with the show form, as the Hook function should return as fast possible (< 50 ms) or your will end up with deadlock (and a crashed app) very quickly. Never set a breakpoint inside the Hook procedure, or you will kill your IDE (maybe crash, maybe hung, maybe some wierd state were you can never leave a breakpoint and you can't stop debugging). If you have a ton of long running functions you want to run based on a keypress, then set up a stack of actions to perform in the timer. Using a hook library is very powerful, but with great power comes great crashes...
I have no experience with that hooks library, but my guess is that you should do very little in the HookProc procedure itself. You are being called directly from the Windows API, rather than via the VB6 runtime. I'm not surprised that showing forms crashes everything out as you describe. Was there any advice on the vbAccelerator site about what sort of code to put in HookProc? vbAccelerator is an excellent site by the way.
I suggest you just set a flag variable somewhere to indicate that frmNewReport should be shown. You should have a Timer running with a short tick interval, say 100 milliseconds, which checks the flag variable: if the flag is set, clear the flag and show the form.
I've found a solution to my own question, its still crash-prone if not handled carefully, but now my application actually responds to key combinations that I wanted, Ctrl + N, Ctrl + O, etc.
Following is my rectified code that works fine as far as I know. Do suggest if you find any bug in it that lead to crash my application.
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Private Property Get CtrlPressed() As Boolean
CtrlPressed = (GetAsyncKeyState(vbKeyControl) <> 0)
End Property
Private Function IWindowsHook_HookProc(ByVal eType As EHTHookTypeConstants, ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long, bConsume As Boolean) As Long
If wParam = vbKeyN Then
If CtrlPressed Then
LoadFormNewReport 'Method that opens Child Form 'New Report'
End If
bConsume = True
ElseIf wParam = vbKeyS Then
If CtrlPressed Then
SaveNewReport 'Method that saves new Report
End If
bConsume = True
ElseIf wParam = vbKeyF5 Then
If Not CtrlPressed Then
frmSettings.Show 'This form needs to be displayed Modally but if tried so then crashes application along with VB IDE, other short-cuts work fine.
bConsume = True
End If
End If
End Function

Is there a way to read an .ini file into memory and then read particular values from it?

I've got a situation where an ini file is in memory (in a string variable) and I'd like to read values out of it without writing the ini file data to disk.
UPDATE:This is data that I do not want to write to the HD. I'm downloading it from a web server into memory and then getting some data.
Is there any way to do that in VB6? Maybe with a Win API call?
Clay,
Check out this article at DevX.com
Read/Write INI without using API
This should get you pointed in a good direction. The modules are a bit dirty and do, at this point, require a path for the INI to be stored. Instead simply modify the modules to use your string directly and you should receive the desired result. Let me know how this works out for you.
The ini file is to be stored on hard disk. If you want to save in registry instead (this should be added to the registry file too), you can use these functions:
SaveSetting
GetSetting
If you don't want to save it on disk I think it might be difficult to use any specific API calls. But if it's an ini file it should be in a structured format, why not just loop through it until the section you want and then read the values you want from it.
It's been a long time but it should be something like this I think:
Just Split it on newlines to get an array of lines, then each section should start in a certain format and for each line in there you check if it contains an = I think, and if so everything to the left of the first = is the name of the value and everything to the right of it is the value.
Declare the two Windows API function imports
Public Declare Function GetPrivateProfileStringA Lib "kernel32.dll" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
Public Declare Function WritePrivateProfileStringA Lib "kernel32.dll" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long
For reading
sReturn = Space(255)
sReturn = Left(sReturn, GetPrivateProfileStringA(header, key, defaultReturn, sReturn, 255, filePath))
For writting
WritePrivateProfileStringA header, key, Datum, filePath
Remember the structure of an INI file is
[header]
key=data

GetPrivateProfileString Oddity

I was just tinkering around with calling GetPrivateProfileString and GetPrivateProfileSection in kernel32 from .NET and came across something odd I don't understand.
Let's start with this encantation:
Private Declare Unicode Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringW" ( _
ByVal lpApplicationName As String, _
ByVal lpKeyName As String, _
ByVal lpDefault As String, _
ByVal lpReturnedString() As Char, _
ByVal nSize As Int32, _
ByVal lpFileName As String) As Int32
If I pass an lpApplicationName (section), no lpKeyName and no lpDefault, I should get all of the keys for that section, and indeed I do: 50% of the time.
If the ini file has the lpApplicationName starting on the first line, the buffer returns nothing. If lpApplicationName stats on the second line in the file, it returns the expected values.
At first I though it was a matter of using the W version and Unicode in the Declare, but changing those seems to have no effect.
What am I missing?
Check to see if the file you are opening has a byte order mark (a few bytes marking the type of text encoding).
These Windows API calls don't seem to grok byte order marks and is causes them to miss the first section (hence everything works fine if there is a blank line).
Good call. Editing the ini file in VS.NET is of course (Duh) adding a utf-8 BOM. Grrr.
Opening it in notepad and doing a SaveAs ASCII yields the expected results.
So obvious. So obtuse. Another hour down the crapper. :-)
Thanks!
-=Chris

Resources