Quantcast
Channel: VBForums - API
Viewing all 209 articles
Browse latest View live

Question about CreateProcess and closing handles

$
0
0
So according to https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx I need to close the process and thread handles in the PROCESS_INFORMATION structure, when I'm done using them. But what about if I need them for the entire time that the created process is running? When the created process finishes running (such as clicking on the X button on the main window of the created process to close the program), doesn't a program that finishes running and closes down automatically close its own handles?

Questions about STARTUPINFO structure in VB6

$
0
0
Since VB6 is a bit quirky with userdefined types, and all the rules it has for handling them internally, while the results withing VB6 might appear fine, when passing a UDT to another process like an API dll file, things might not be as fine as you think, and this makes them not 100% equivalent to the more standard concept of a "struct" in VC++ (which is how you will usually see structures being defined in online documentation). I have yet to find an official Microsoft documentation for how the STARTUPINFO structure should be defined as a UDT in VB6.

For example, in STARTUPINFO structure the fields lpReserved, lpDesktop, and lpTitle are all pointers to strings. So should I define these As Long when making a userdefined type in VB6, so that the fields will represent 32bit pointers? Or should I define them As String, and assume that VB6 will convert them to pointers when passing the STARTUPINFO structure to the CreateProcess API function that I'm trying to use? Same thing with the 3 fields wShowWindow, cbReserved2, and lpReserved2. First 2 of these fields are defined As Integer and the 3rd one As Byte according to someone's posting at http://stackoverflow.com/questions/2...ce-it-finishes but there is a problem here. Are these really supposed to be 2byte and 1byte fields as shown? Or are they supposed to be 4byte fields that represent pointers to 2byte and 1byte data fields? And if they are supposed to be 4byte pointers, but they are defined As Integer (2bytes) and As Byte (1byte), will VB6 automatically convert them to 4byte pointers when it passes the STARTUPINFO UDT to the CreateProcess API function?

Here's an idea of the confusion I'm having.

Here's how one person defined the STARTUPINFO structure on the above mentioned webpage.
Code:

Private Type STARTUPINFO
        cb              As Long
        lpReserved      As Long
        lpDesktop      As Long
        lpTitle        As Long
        dwX            As Long
        dwY            As Long
        dwXSize        As Long
        dwYSize        As Long
        dwXCountChars  As Long
        dwYCountChars  As Long
        dwFillAttribute As Long
        dwFlags        As Long
        wShowWindow    As Integer
        cbReserved2    As Integer
        lpReserved2    As Byte
        hStdInput      As Long
        hStdOutput      As Long
        hStdError      As Long
End Type


But here's how it's defined in ApiViewer2004.
Code:

Private Type STARTUPINFO
        cb As Long
        lpReserved As Long
        lpDesktop As Long
        lpTitle As Long
        dwX As Long
        dwY As Long
        dwXSize As Long
        dwYSize As Long
        dwXCountChars As Long
        dwYCountChars As Long
        dwFillAttribute As Long
        dwFlags As Long
        wShowWindow As Integer
        cbReserved2 As Integer
        lpReserved2 As Byte
        hStdInput As Long
        hStdOutput As Long
        hStdError As Long
End Type


Notice the differences in how some of the fields are defined. These differences will produce definite differences in the size of the structure, which will change the value that I need to supply to the cb field before passing the structure to the CreateProcess API function. And only one of these 2 is correct. Or it might be that neither of them is correct, and there might be a 3rd way of defining it that is actually correct. I really am going to need some help here with this.

What exactly are the parameters for the API method called DispCallFunc?

$
0
0
Looking at MSDN I see
Code:

HRESULT DispCallFunc(
  void      *pvInstance,
  ULONG_PTR  oVft,
  CALLCONV  cc,
  VARTYPE    vtReturn,
  UINT      cActuals,
  VARTYPE    *prgvt,
  VARIANTARG **prgpvarg,
  VARIANT    *pvargResult
);

Some of these are confusing, because they don't specify a byte-size for the parameter, but instead give it in some cryptic way that is great for VC++, but not so great for those wanting to figure out how to use it in VB6.

For example, what is a "void"? I thought it meant "don't fill in this parameter, because it's unused", but I'm not sure. Some are obvious like ULONG_PTR, means an unsigned long value which holds a memory address (a pointer). VB6 doesn't have any unsigned Long, but it has the standard (signed) Long, which should usually work. Other cryptic ones are VARTYPE. What type of variable is a VARTYPE? Is it equivalent to a Long in VB6? Or is it the equivalent to an Integer in VB6 (what VC++ calls a Short)?

And for goodness sake, what is a VARIANTARG? I think (based on some other things I've read), this is where I feed some pointers to the input parameters to the function that is to be called, to the DispCallFunc method. But what kind of input is it expecting?
Is it expecting an array of Long values that are pointers? Is it expecting a Variant that holds an array of Long values that are pointers? Is it expecting an array of Variants that hold Long values that are pointers? Or is it expecting a Variant that holds an array of Variants that hold Long values that are pointers?

Any help here at using this in VB6 would be great. There are hardly any examples on the net that show its use at all (even in C based languages), and from what I can tell, there are none that show its use in VB6.

I wish there was just some tutorial that said "These are the data types of the parameters of the DispCallFunc method, and here's what the function expects you to put into them. ......". But nope, nothing of the sort. Can somebody here on VbForums just explain straight out, what is the correct declare statement for this thing, and how do I use it to call a variety of different methods in my Module1 module? Some things I'd like to know how to use it with are:
A function with no input parameters, but with an output parameter (like maybe a random number generator).
A function with some input parameters, and a return value.
A sub with some input parameters, and no return value.
A sub with no input parameters, and no return value (but maybe it does something else, like clear the screen)
Calling a function or sub that is not in my Module1 module, but rather in an STDCALL DLL file.
Calling a function or sub that is not in my Module1 module, but rather in an CDECL DLL file.
Calling a function or sub that is in a COM object (such as from an ActiveX DLL or OCX file)
Calling a function or sub that is in a VB6 Class (such as a method in Class1)

Any help with its general use (like how to properly declare it, and what the parameters mean), and any help for these specific listed uses from someone who's an expert at using DispCallFunc, would be very helpful.

Retrieve data from another program into VBA

$
0
0
I'm trying to retrieve data from another software, called CMA Series 4 into my Excel. I already was able to get a handler for the chart i wanna retrieve that data, but from now, i have no idea how to proceed to obtain that information.

Using Microsoft Spy ++, i was able to sucessfully acess the object in CMA, that is from "fpSpread 60" class. But how do i retrieve the data stored in it? That's the code:

Code:

Sub GetBookData()

Dim BookTitle As String
Dim BookClass As String

'----------------------------------------------------------'
BookTitle = "[012] POMO4 - Livro de Ofertas"
'----------------------------------------------------------'

hwnd = FindWindow("CMAGRAPHIC_MDI", vbNullString)
    Livro1 = FindWindowEx(hwnd, 0&, "MDIClient", vbNullString)
    Livro2 = FindWindowEx(Livro1, 0&, vbNullString, BookTitle) 'Classe alterável
    Livro3 = FindWindowEx(Livro2, 0&, "SysTabControl32", vbNullString)
    Livro4 = FindWindowEx(Livro3, 0&, "AfxMDIFrame90", vbNullString)

    'Necessaria criação dessa porcaria dessa árvore de referencia porque a estrutura desse lixo de CMA é essa...
    Livro5 = FindWindowEx(Livro4, 0&, "AfxFrameOrView90", vbNullString)
        Livro6 = FindWindowEx(Livro4, Livro5, "AfxFrameOrView90", vbNullString)
        Livro7 = FindWindowEx(Livro4, Livro6, "AfxFrameOrView90", vbNullString)
        Livro8 = FindWindowEx(Livro4, Livro7, "AfxFrameOrView90", vbNullString)
        Livro9 = FindWindowEx(Livro4, Livro8, "AfxFrameOrView90", vbNullString)
        Livro10 = FindWindowEx(Livro4, Livro9, "AfxFrameOrView90", vbNullString)

    Livro11 = FindWindowEx(Livro10, 0&, "fpSpread60", vbNullString)
        Livro12 = FindWindowEx(Livro10, Livro11, "fpSpread60", vbNullString)
        Livro13 = FindWindowEx(Livro10, Livro12, "fpSpread60", vbNullString)
        Livro14 = FindWindowEx(Livro10, Livro13, "fpSpread60", vbNullString)
        Livro15 = FindWindowEx(Livro10, Livro14, "fpSpread60", vbNullString)
        HwndBook = FindWindowEx(Livro10, Livro15, "fpSpread60", vbNullString) '---- FINALMENTE ----'

'MsgBox HwndBook
MsgBox HwndBook

End Sub

And, i'm posting also a print screen from the place i wanna grab that info:

http://imagizer.imageshack.us/a/img673/7043/yeo3nE.png

SetWindowPos

$
0
0
First off i'm not quite sure if this question belongs in this section or not, so if a mod feels it would better answered somewhere else please move it.

So I am trying to host a WinWord 2010 app in my vb.net application. After reading allot I found that this cannot really be done, but what could be done is almost mimic the same thing as the old oleControl that vb6 had to host excel and word.

By using some API's we can set the parent of the window that the Word app is in to a window in my application. I have tested this code against Word 2003 and it does indeed work ok, however when I ran it against a Word 2010 installation it kind-of fails as the bottom of the Word app is cut off.

I can get it to work correctly but not the way I want it to work. I wish to have some space above the Word window for some other controls that I'm gonna have to insert fields into the document and such.

Any ideas how to position this Word window within my panel?

Here is the complete code:
Create a project: add a winForm name clsEmbedWord, add a panel named WordPanel, Add a groupbox-docked to top of form.

Code:

Option Strict Off

Imports Microsoft.Office.Interop.Word
Imports Microsoft.Office.Interop
Imports System.Runtime.InteropServices


Public Class clsEmbedWord

#Region "Enums"
    <Flags()> _
    Private Enum SetWindowPosFlags As UInteger
        ''' <summary>If the calling thread and the thread that owns the window are attached to different input queues,
        ''' the system posts the request to the thread that owns the window. This prevents the calling thread from
        ''' blocking its execution while other threads process the request.</summary>
        ''' <remarks>SWP_ASYNCWINDOWPOS</remarks>
        SynchronousWindowPosition = &H4000
        ''' <summary>Prevents generation of the WM_SYNCPAINT message.</summary>
        ''' <remarks>SWP_DEFERERASE</remarks>
        DeferErase = &H2000
        ''' <summary>Draws a frame (defined in the window's class description) around the window.</summary>
        ''' <remarks>SWP_DRAWFRAME</remarks>
        DrawFrame = &H20
        ''' <summary>Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to
        ''' the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE
        ''' is sent only when the window's size is being changed.</summary>
        ''' <remarks>SWP_FRAMECHANGED</remarks>
        FrameChanged = &H20
        ''' <summary>Hides the window.</summary>
        ''' <remarks>SWP_HIDEWINDOW</remarks>
        HideWindow = &H80
        ''' <summary>Does not activate the window. If this flag is not set, the window is activated and moved to the
        ''' top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter
        ''' parameter).</summary>
        ''' <remarks>SWP_NOACTIVATE</remarks>
        DoNotActivate = &H10
        ''' <summary>Discards the entire contents of the client area. If this flag is not specified, the valid
        ''' contents of the client area are saved and copied back into the client area after the window is sized or
        ''' repositioned.</summary>
        ''' <remarks>SWP_NOCOPYBITS</remarks>
        DoNotCopyBits = &H100
        ''' <summary>Retains the current position (ignores X and Y parameters).</summary>
        ''' <remarks>SWP_NOMOVE</remarks>
        IgnoreMove = &H2
        ''' <summary>Does not change the owner window's position in the Z order.</summary>
        ''' <remarks>SWP_NOOWNERZORDER</remarks>
        DoNotChangeOwnerZOrder = &H200
        ''' <summary>Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to
        ''' the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent
        ''' window uncovered as a result of the window being moved. When this flag is set, the application must
        ''' explicitly invalidate or redraw any parts of the window and parent window that need redrawing.</summary>
        ''' <remarks>SWP_NOREDRAW</remarks>
        DoNotRedraw = &H8
        ''' <summary>Same as the SWP_NOOWNERZORDER flag.</summary>
        ''' <remarks>SWP_NOREPOSITION</remarks>
        DoNotReposition = &H200
        ''' <summary>Prevents the window from receiving the WM_WINDOWPOSCHANGING message.</summary>
        ''' <remarks>SWP_NOSENDCHANGING</remarks>
        DoNotSendChangingEvent = &H400
        ''' <summary>Retains the current size (ignores the cx and cy parameters).</summary>
        ''' <remarks>SWP_NOSIZE</remarks>
        IgnoreResize = &H1
        ''' <summary>Retains the current Z order (ignores the hWndInsertAfter parameter).</summary>
        ''' <remarks>SWP_NOZORDER</remarks>
        IgnoreZOrder = &H4
        ''' <summary>Displays the window.</summary>
        ''' <remarks>SWP_SHOWWINDOW</remarks>
        ShowWindow = &H40
    End Enum
#End Region

    Public Const HWND_TOPMOST = -1

    ' Retrieves a handle to the top-level window whose class name and window
    ' name match the specified strings. This function does not search
    ' child windows. This function does not perform a case-sensitive search.
    <DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function FindWindowByCaption( _
    ByVal zero As IntPtr, _
    ByVal lpWindowName As String) As IntPtr
    End Function

    ' Changes the parent window of the specified child window.
    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Public Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
    End Function

    ' Changes the size, position, and Z order of a child, pop-up, or top-level window.
    ' These windows are ordered according to their appearance on the screen.
    ' The topmost window receives the highest rank and is the first window in the Z order.
    <DllImport("user32.dll", SetLastError:=True)> _
    Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, _
                                        ByVal hWndInsertAfter As IntPtr, _
                                        ByVal X As Integer, ByVal Y As Integer, _
                                        ByVal cx As Integer, ByVal cy As Integer, _
                                        ByVal uFlags As SetWindowPosFlags) As Boolean

    End Function

    Private WithEvents ObjWord As Application
    Private WordWND As Integer


    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        ObjWord.Quit(False)
    End Sub

    Private Sub clsEmbedWord_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        Me.WordPanel.Top = Me.Top + Me.GroupBox1.Height + 10
        Me.WordPanel.Height = Me.Height - Me.GroupBox1.Height
        Try

            Me.Cursor = Cursors.AppStarting

            ' Load Word and make invisible
            ObjWord = New Word.Application
            ObjWord.Visible = False

            ' Set a custom window title to make it
            ' easier to find the window handle
            ObjWord.Caption = "I.G.O.R.- WORD"
            WordWND = FindWindowByCaption(vbNullString, "I.G.O.R.- WORD")

            ' Make Word a child window of the picture control
            SetParent(WordWND, Me.WordPanel.Handle.ToInt32())

            ObjWord.WindowState = Word.WdWindowState.wdWindowStateNormal

            ' Positon Word to the coordinates of the picture control
            SetWindowPos(WordWND, HWND_TOPMOST, 0, 0, Me.WordPanel.Bounds.Width, Me.WordPanel.Bounds.Height - 20, Nothing)

            ' Add a document and make Word visible
            ObjWord.Documents.Add()
            ObjWord.Visible = True

            Me.Cursor = Cursors.Arrow

        Catch Ex As Exception
            MsgBox(Ex.ToString, MsgBoxStyle.OkOnly Or MsgBoxStyle.SystemModal, "Exception")
        End Try
    End Sub

 
End Class

Question about CreateFile parameter dwCreationDisposition

$
0
0
If you use Truncate (the value 5) for this parameter, it opens the file and then removes all the bytes of data in the file when it is opened, but does it allow further access (reading and writing) after this truncation operation? Or would I need to close it and reopen it with a different CreationDisposition value after this to write more data to the file?

Questions about DLL calling conventions

$
0
0
Ok so using GoAsm assembler and GoLink linker, along with the Easy Code GUI for the GoAsm suite, I wrote my own DLL file, complete with some exported functions, entirely in assembly language. Problem is, Visual Basic 6 kept giving me the Bad DLL Calling Convention error.

After spending an hour of troubleshooting and trial and error trying to figure out what part of my function VB6 didn't like, I finally figured that I needed to PUSH the EDI register onto the stack at the beginning of my DLL function (part of its operation modified the EDI register), and then at the end of my function I needed to POP the value out of the stack back into the EDI register. After that, I no longer got any errors at all from VB6 about Bad DLL Calling Convention.

Why did VB6 not like the fact that the EDI register got modified? What is so special about that register? In the course of my function operating, other registers also got changed (EBX, ECX, EDX, and ESI). Yet the only one that caused VB6 to throw an error was the EDI register.

API / Code for adding text equal to the filename to a PDF Document

$
0
0
Hi there,

I need to add the file name to the top right an existing PDF document (it is a scan of an invoice). I'm using MS Access & VB to process the scan, assign the file name and email the PDF off to the OCR capture service. All I'm short of is the code / API to add the file name to the PDF document that I've created while scanning. CutePDF has the functionality to add the file name to the header of an existing PDF document, but it seems to lack the functionality to do lots of files at once and then save it back as the same file name.

Does anyone of there have experience with this type of thing?

Thanks!

Possible memory problem with using Windows API to get icons

$
0
0
Hello,

I'm currently writing a small file manager. It's just a small program I'm writing in my spare time for fun. It's going well, except for this problem. I'm trying to use the Windows API to get some 48x48 icons associated with files for use in drawing the UI. Below is the code I'm using for this. The reason that I'm using these API calls and not simply doing Icon.ExtractAssociatedIcons is because I want those 48x48 icons. ExtractAssociatedIcon is limited to 32x32 icons.

It works properly for a while, but I've found that if this code is used too many times, it crashes. For example, if I open a folder like C:\Windows\System32 where this code literally has to be executed thousands of times for thousands of files, it works for a little bit (a few seconds), then crashes. Or, I can open a folder like C:\ and it'll work fine, but then if I open too many copies of C:\, it'll eventually crash.

The stack trace is below.

Quote:

System.Reflection.TargetInvocationException was unhandled by user code
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle._SerializationInvoke(Object target, SignatureStruct& declaringTypeSig, SerializationInfo info, StreamingContext context)
at System.Reflection.RuntimeConstructorInfo.SerializationInvoke(Object target, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Resources.ResourceReader.DeserializeObject(Int32 typeIndex)
at System.Resources.ResourceReader.LoadObjectV2(Int32 pos, ResourceTypeCode& typeCode)
at System.Resources.ResourceReader.LoadObject(Int32 pos, ResourceTypeCode& typeCode)
at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase, Boolean isString)
at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase)
at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture, Boolean wrapUnmanagedMemStream)
at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture)
at TFMP_Framework.My.Resources.Resources.get_unknownIcon_medium() in D:\Documents\Visual Studio 2010\Projects\TFMP Framework\My Project\Resources.Designer.vb:line 118
at TFMP_Framework.FileInfoAPI.GetIcon(String path, ImageListIconSize iconSize, Boolean isDirectory, SHFILEINFO& shinfo) in D:\Documents\Visual Studio 2010\Projects\TFMP Framework\FileInfoAPI.vb:line 130
at Villanova.FBIcon.LoadIconDetails(Object sender, DoWorkEventArgs e) in D:\Documents\Visual Studio 2010\Projects\Villanova\FBIcon.vb:line 63
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
InnerException: System.ComponentModel.Win32Exception
ErrorCode=-2147467259
Message=The operation completed successfully
NativeErrorCode=0
Source=System.Drawing
StackTrace:
at System.Drawing.Icon.Initialize(Int32 width, Int32 height)
at System.Drawing.Icon..ctor(SerializationInfo info, StreamingContext context)
InnerException:
I've done my research on the InnerException I'm getting (The operation completed successfully), and according to the internet it always seems to be related to the memory. Either the application isn't allocating enough memory for the task, or the application has reached its memory limit, or the application has reached some other hard limit (like a GDI handles limit). The problem is, I believe that the garbage is being properly collected (correct me if I'm wrong). I'm using DestroyIcon (another Windows API call) to destroy the handle to the Icon after its use, and I'm disposing the BackgroundWorker when it has finished executing its thread.

And also, I'm using a BackgroundWorker and executing the calls to get the icons in a background thread (it's too slow if I don't). I initially thought it might be a multi-threading problem, but even when I try to run this exact same code on the main thread, it fails with the same exception.

In my code, there are some bits that are commented out that have to do with caching the icons. I experimented with caching the icons. For example, if I cache the icon that's associated with DLL files, then I only have to invoke the Windows API once to get the icon and cache it, then I can use the cached copy of the icon for the other 2000 DLLs in the folder). That works a lot better. A lot. To the point where I can open many copies of a folder that has thousands of files in it and be fine. But I feel that that's just a workaround. It's just putting off the problem, not really solving it.

I've included the code to the Windows API calls I'm using. If you need anything else, let me know and I'll get it to you.

I've spent a ton of time troubleshooting and researching this, and at this point it feels like I'm spinning my wheels. I'm almost wondering if this is just a limitation that's unsolvable. Any assistance would be greatly appreciated. :)

And Mods, if I've posted in the wrong section, I apologize. Feel free to move it as you see fit.

- Colin

Code:

' This class is a container containing a collection of properties, events, and Windows API functions.
' This is intended to make it easy to invoke the Windows API to get some detailed information about files.
Imports System.Runtime.InteropServices
Public Class FileInfoAPI
    Private Shared imageListSmall As IImageList = Nothing
    Private Shared imageListMedium As IImageList = Nothing
    Private Shared imageListLarge As IImageList = Nothing
    ' SHGetFileInfo gets some low-level information about files like the handle (pointer) to the file's icon, a file description, and attributes:
    <DllImport("Shell32.dll")> _
    Public Shared Function SHGetFileInfo(ByVal pszPath As String, ByVal dwFileAttributes As UInteger, ByRef psfi As SHFILEINFO, ByVal cbfileInfo As UInteger, ByVal uFlags As SHGFI) As Integer
    End Function
    ' DestroyIcon erases an HIcon from memory; in this context, it's used to prevent memory leaks:
    <DllImport("User32.dll")> _
    Public Shared Function DestroyIcon(ByVal hIcon As IntPtr) As Integer
    End Function
    <DllImport("Shell32.dll", EntryPoint:="#727")> _
    Public Shared Function SHGetImageList(iImageList As Integer, ByRef riid As Guid, ByRef ppv As IImageList) As Integer
    End Function
    ' here's a structure that will contain information returned by SHGetFileInfo:
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure SHFILEINFO
        Public Sub New(ByVal b As Boolean)
            hIcon = IntPtr.Zero
            iIcon = 0
            dwAttributes = 0
            szDisplayName = ""
            szTypeName = ""
        End Sub
        Public hIcon As IntPtr
        Public iIcon As Integer
        Public dwAttributes As UInteger
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> _
        Public szDisplayName As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
        Public szTypeName As String
    End Structure
    Public Structure RECT
        Dim left As Long
        Dim top As Long
        Dim right As Long
        Dim bottom As Long
    End Structure
    ' just some constants used by SHGetFileInfo:
    Public Enum SHGFI
        Icon = &H100
        SmallIcon = &H1
        LargeIcon = &H0
        ExtraLargeIcon = &H2
        OpenIcon = &H2
        ShellIcon = &H4
        DisplayName = &H200
        Typename = &H400
        SysIconIndex = &H4000
        UseFileAttributes = &H10
        Directory = &H10
    End Enum
    Public Enum ImageListIconSize
        SmallIcon = &H1
        MediumIcon = &H0
        LargeIcon = &H2
    End Enum
    Public Shared Function GetInfo(ByVal strPath As String, ByVal isDirectory As Boolean) As SHFILEINFO
        ' here's the actual function that will be called which will invoke the Windows API
        ' this is just some wrapper code to make invoking the API easier
        Dim info As New SHFILEINFO(True)
        Dim cbFileInfo As Integer = Marshal.SizeOf(info)
        Dim flags As SHGFI
        flags = SHGFI.SysIconIndex Or SHGFI.Icon Or SHGFI.UseFileAttributes Or SHGFI.Typename Or SHGFI.DisplayName
        SHGetFileInfo(strPath, IIf(isDirectory = True, SHGFI.Directory, 256), info, CType(cbFileInfo, UInteger), flags)
        If info.hIcon <> IntPtr.Zero Then
            DestroyIcon(info.hIcon)
        End If
        Return info
    End Function
    Public Shared Sub GetSystemImageListHandle(ByVal size As ImageListIconSize)
        Dim imageListGuid As New Guid("46EB5926-582E-4017-9FDF-E8998DAA0950")
        If size = ImageListIconSize.SmallIcon Then
            SHGetImageList(CType(size, Integer), imageListGuid, imageListSmall)
        ElseIf size = ImageListIconSize.MediumIcon Then
            SHGetImageList(CType(size, Integer), imageListGuid, imageListMedium)
        Else
            SHGetImageList(CType(size, Integer), imageListGuid, imageListLarge)
        End If
    End Sub
    Public Shared Function GetIcon(ByVal path As String, ByVal iconSize As ImageListIconSize, ByVal isDirectory As Boolean, ByRef shinfo As SHFILEINFO) As Icon
        'Dim CachedIcon As Icon = Nothing
        'Dim GotCachedIconAlready As Boolean
        'If isDirectory = True Then
        '    GotCachedIconAlready = False
        'Else
        '    GotCachedIconAlready = CachedIconList.FindCachedIcon(Functions.GetExtensionOfPath(path), iconSize, CachedIcon)
        'End If
        'If GotCachedIconAlready = True Then
        '    Return CachedIcon
        'Else
        If iconSize = ImageListIconSize.SmallIcon Then
            Do Until imageListSmall IsNot Nothing
                GetSystemImageListHandle(iconSize)
            Loop
        ElseIf iconSize = ImageListIconSize.MediumIcon Then
            Do Until imageListMedium IsNot Nothing
                GetSystemImageListHandle(iconSize)
            Loop
        Else
            Do Until imageListLarge IsNot Nothing
                GetSystemImageListHandle(iconSize)
            Loop
        End If
        Dim icn As Icon = Nothing
        'Do Until icn IsNot Nothing
        shinfo = GetInfo(path, isDirectory)
        Dim iconIndex As Integer = shinfo.iIcon
        Dim hIcon As IntPtr = IntPtr.Zero
        If iconIndex <> Nothing Then
            If iconSize = ImageListIconSize.SmallIcon Then
                imageListSmall.GetIcon(iconIndex, CType(&H0, Integer), hIcon)
            ElseIf iconSize = ImageListIconSize.MediumIcon Then
                imageListMedium.GetIcon(iconIndex, CType(&H0, Integer), hIcon)
            Else
                imageListLarge.GetIcon(iconIndex, CType(&H0, Integer), hIcon)
            End If
        End If
        If hIcon <> IntPtr.Zero Then
            icn = CType(Icon.FromHandle(hIcon).Clone(), Icon)
            DestroyIcon(hIcon)
        Else
            If iconSize = ImageListIconSize.SmallIcon Then
                icn = My.Resources.unknownIcon_small
            ElseIf iconSize = ImageListIconSize.MediumIcon Then
                icn = My.Resources.unknownIcon_medium
            Else
                icn = My.Resources.unknownIcon_large
            End If
        End If
        'Loop
        'CachedIconList.AddCachedIcon(icn, Functions.GetExtensionOfPath(path), iconSize)
        Return icn
        'End If
    End Function
    <ComImportAttribute()> _
    <GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950")> _
    <InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
    Interface IImageList
     
        ... shortened to get post within character limit ...

        <PreserveSig()> _
        Function GetIcon(i As Integer, flags As Integer, ByRef picon As IntPtr) As Integer

        ... shortened to get post within character limit ...

    End Interface
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure IMAGELISTDRAWPARAMS
        Public cbSize As Integer
        Public himl As IntPtr
        Public i As Integer
        Public hdcDst As IntPtr
        Public x As Integer
        Public y As Integer
        Public cx As Integer
        Public cy As Integer
        Public xBitmap As Integer
        ' x offest from the upperleft of bitmap
        Public yBitmap As Integer
        ' y offset from the upperleft of bitmap
        Public rgbBk As Integer
        Public rgbFg As Integer
        Public fStyle As Integer
        Public dwRop As Integer
        Public fState As Integer
        Public Frame As Integer
        Public crEffect As Integer
    End Structure
    <StructLayout(LayoutKind.Sequential)> _
    Public Structure IMAGEINFO
        Public hbmImage As IntPtr
        Public hbmMask As IntPtr
        Public Unused1 As Integer
        Public Unused2 As Integer
        Public rcImage As RECT
    End Structure

How do I make a resetable timer?

$
0
0
I have been looking at these API calls:
the function GetTickCount

the pair of functions
QueryPerformanceFrequency
QueryPerformanceCounter

and this set of functions
timeBeginPeriod
timeGetTime
timeEndPeriod

All of these are missing the ability to reset the time to 0. The timeBeginPeriod doesn't do what it sounds like. It doesn't reset the timer to 0. Instead it simply initializes the timer with a certain level of precision (use 1 for highest precision, forcing it to have a precision no worse than 1 millisecond). In all cases, they get the time (with varying levels of precision, depending on which API function you are using) from the hardware clock chip in the PC, which records the amount of time since the PC was last powered on. None of these API calls give you the ability to reset the internal hardware clock.

A simple workaround is to subtract the current clock value from an earlier one to calculate the time elapsed since then. But that has a problem. The moment you go from &h7FFFFFFF to &h80000000, you are going to have a problem, because VB6 uses signed values only. Even if you handle the numbers as Currency data type (CopyMemory from a Long to a Currency, and then multiply by 10000) you still are going to have a problem on the tick that it goes from 0xFFFFFFFF back to 0x00000000. If you set the initial value when the time is 0xFFFFFFF0, in only 16 milliseconds it will jump back to 0x00000000, messing up anything that depended on your timer working properly (such as selecting a frame to display from a list of loaded frames, based on the timer's current tick count, in a video player for example).

So here's how to suspend a process via Windows API

$
0
0
I'd been trying to figure it out for a long time. You can use TerminateThread to terminate a thread, or SuspendThread to suspend a thread. While TerminateProcess is the process equivalent to TerminateThread, it appears at first that there is no process equivalent to SuspendThread. There is no SuspendProcess. Of course you can use the Tool Help functions to enumerate all the threads of a process and then suspend each thread separately with SuspendThread, this makes a simple task unnecesarilly complicated, and also there's no guaranty that, if one thread depends on the activity of another thread, that you won't mess up this thread-to-thread interaction. It appears at first that there's just no reasonable workaround for this lack of a SuspendProcess API function. But there is a workaround. In fact it's part of the Windows API. It's just not documented (even the name of the function never appears in the official MSDN website). You see, there's this really neat function in ntdll.dll called NtSuspendProcess, as well as NtResumeProcess so you can get the suspended process running again. And they work exactly as expected. Both functions take only one argument, the handle to the process to be suspended or resumed.

Theoretically you are never supposed to use undocumented functions when writing a program, because there's no guaranty that Microsoft is going to keep those functions in their system DLL files indefinitely. However, I'm using a PC with Windows 7 with SP1, and both of these functions work fine so far. And according to stuff I've read online, these function first became available in Windows XP, so it should work in XP, Vista, and 7 (not making any promises about 8, 8.1, or 10 though). Below are the Declare statements for these 2 functions.
Code:

Private Declare Function NtSuspendProcess Lib "ntdll.dll" (ByVal hProcess As Long) As Long
Private Declare Function NtResumeProcess Lib "ntdll.dll" (ByVal hProcess As Long) As Long


They appear to work on a counter system. Each time you run the NtSupsendProcess function, it must increment a counter, because in order to resume the process you need to run the NtResumeProcess just as many times as you ran the NtSuspendProcess function. Running NtResumeProcess more times has no effect at all (for example, you don't need to run NtSuspendProcess just as many times as you ran NtResumeProcess in order to suspend the process). As for the function's return value, I don't know what it is supposed to be, but I've found it always is 0. I assume 0 means the function had no error, and that a non-zero value would indicate that the function failed to work. This applies for both the NtSuspendProcess and NtResumeProcess functions. As for what process access rights these functions need, I don't know, since they are undocumented. However they have always worked for me when I use them on any process opened with OpenProcess and when I use the constant MAXIMUM_ALLOWED (value = &H2000000) for the access flags in the OpenProcess function (which guaranties that the OpenProcess function doesn't fail, and that all access rights that my application is allowed when interacting with the target process are in fact activated).

Questions about file handles and locking

$
0
0
What API function can be used to determine what file handles already exist for a file, being accessed by another program?

I know that if there's a file you want to delete and another program has not released its lock on it, you can use software called Unlocker or another one called Lock Hunter, and what it does it does is show you what programs currently have a file locked, and allow you to forcibly unlock it. This is very useful if another program had opened a file but failed to close it properly (bug in the program), and now you want to delete the file, but don't want to have to close down the program associated with the lock on that file.

But my question is, what API calls are such programs as Unlocker actually using? Usually the way you lock or unlock a file is to use CreateFile to open it, which gives you a file handle. You then use that file handle with the LockFile and UnlockFile API calls to lock and unlock the file. But these 2 API calls assume you have access to the file handle to start with. If I'm trying to unlock a file locked by another program however, I do not have access to that particular handle. Is there some API call that allows you to get the file handle associated with another program's accessing of a particular file? If not, how do programs like Unlocker and Lock Hunter actually unlock all the locks associated with a particular file?

Need some help with clipboard access

$
0
0
So I need to allocate memory and get an hMem handle to pass to the SetClipboardData function. Which should I be using, the GlobalAlloc or LocalAlloc functions?

And when getting data out of the clipboard, do I need to be using LocalLock or GlobalLock on the returned hMem handle from the GetClipboardData function, in order to access the returned data?

And as for destroying the memory, I know it says that the system takes over the memory object when the clipboard is open, but what about after I close the clipboard with the CloseClipboard function? Then does that return control of the memory object to me (after the system copies the content of the memory object into its own internal clipboard buffer), such that I can then destroy my no longer needed memory object with GlobalFree or LocalFree? Or is the clipboard supposed to keep control of my memory object, and only deallocate the memory when I empty the clipboard?

So is this supported under a WinXP SP or not?

$
0
0
I notice on the MSDN page for CryptBinaryToString there's this bit of info about one of the flags that can be used with this function:
Quote:

Value Meaning

CRYPT_STRING_NOCRLF
0x40000000



Do not append any new line characters to the encoded string. The default behavior is to use a carriage return/line feed (CR/LF) pair (0x0D/0x0A) to represent a new line.

Windows Server 2003 and Windows XP: This value is not supported.

One thing that stands out is the fact that it says that it's not supported under Windows XP. Does that mean the base version of XP? Or does it mean that it won't work even with any service pack (up through SP3)? I have noticed that other pieces of info about various other functions on other MSDN pages say some things won't work under XP with SP1 or SP2, so I'm trying to figure out if when it says won't work under XP, if this means all XP regardless of service pack, or only that it won't work under the original version of XP, but that with an upgrade (possibly just requiring SP1) it will work.

radio thermostat android wear

$
0
0
when I go to the page I liked the link automatically open get info.

how to automatically open a web page http://192.186.1.6/tstat

Then have it adjusted thermostat?

How do I pass WAVEFORMATEX to API functions?

$
0
0
In the function waveOutOpen, you need to pass a WAVEFORMATEX, yet if you do Len and LenB on WAVEFORMATEX, you'll notice that LenB is bigger than Len, indicating that the in-memory copy of a WAVEFORMATEX UDT in VB6 is in fact padded (due to the mixture of Integer and Long data types). Giving a padded copy of the structure to an API function will make it crash. Do you have any idea what the best way to go about this is? WAVEFORMATEX is most certainly required for the use of waveOutOpen.

Click button on a toolbar in another program

$
0
0
Hi,

I have searched the internet looking for how to click a button on a toolbar in another program (not internet Explorer). I found couple, but they are beyond the my capability of understanding. I am stuck at the below part ( I used spy++ to help me to get the windows handles). When I sendmessage I don't know what to put in wparam argument.
.
.
Code:

ChildRet4 = FindWindowEx(ChildRet3, ByVal 0&, "msvb_lib_toolbar", vbNullString)
SendMessage(ChildRet4, WM_COMMAND, ???, ByVal 0)


I appreciate your help.

What's wrong with my usage of WriteConsoleOutputCharacter?

$
0
0
Here's my code.
Code:

Private Declare Function AllocConsole Lib "kernel32.dll" () As Long
Private Declare Function FreeConsole Lib "kernel32.dll" () As Long
Private Declare Function GetStdHandle Lib "kernel32.dll" (ByVal nStdHandle As Long) As Long
Private Declare Function WriteConsoleOutputCharacter Lib "kernel32.dll" Alias "WriteConsoleOutputCharacterA" (ByVal hConsoleOutput As Long, ByVal lpCharacter As String, ByVal nLength As Long, ByRef dwWriteCoord As COORD, ByRef lpNumberOfCharsWritten As Long) As Long

Private Const STD_OUTPUT_HANDLE As Long = -11&

Private Type COORD
    x As Integer
    y As Integer
End Type

Dim hStdOut As Long



Private Sub Form_Load()
AllocConsole
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE)
End Sub



Private Sub Form_Unload(Cancel As Integer)
FreeConsole
End Sub



Private Sub Command1_Click()
Dim Text As String
Dim Pos As COORD
Dim CharCount As Long
Dim ErrNum As Long

Text = "This is a test."
With Pos
    .x = 0
    .y = 0
End With

WriteConsoleOutputCharacter hStdOut, Text, Len(Text), Pos, CharCount
ErrNum = Err.LastDllError
Print CharCount
Print ErrNum
End Sub



What it should do is display the text "This is a test." in the console window, when you click the button Command1. But it's not working. By printing out the variable CharCount (the return value for number of characters written to the console), you can see that it indeed THINKS that it put that text into the console, but if you look at the console you'll see NO TEXT. And if you look at the printed value after CharCount, which is ErrNum (the error number returned from Err.LastDllError, which is the same as the API call GetLastError) it shows 87 (or 0x57 in hexadecimal). I don't know what error 87 means.

SafeArrayLock versus SafeArrayAccessData?

$
0
0
Based on the MSDN descriptions of these, it sounds like they both give you a pointer you can use to access the data stored in a SafeArray. So what exactly is the difference?

Is it possible to do a non-blocking console read?

$
0
0
I would like to be able to read any and all characters that are currently in the console buffer, without knowing how many are in the buffer. If there's one character in the buffer, it should read that one character and return. If there's 100 characters in the buffer, it should read those 100 characters and return. If NO characters are in the buffer it should return immediately without reading anything. It should NEVER stop running (engage in a blocking operation) while waiting for something to read. Is it possible to do this with the console API functions?
Viewing all 209 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>