No announcement yet.

Passing a string to a function inside a WinXP DLL

  • Filter
  • Time
  • Show
Clear All
new posts

  • Passing a string to a function inside a WinXP DLL

    I am trying to write a "wrapper" for the WinXP function
    "rundll32.exe shimgvw.dll,ImageView_Fullscreen %1"
    I have it in a batch file and it works fine but I have been unable to figure out how to pass the filename inside of the PB code. I have;
    DECLARE FUNCTION ImageView_Fullscreen LIB "C:\WINDOWS\system32\shimgvw.dll" ALIAS "ImageView_Fullscreen" (command_str AS STRING) AS LONG
    LOCAL command_str AS STRING
    command_str = COMMAND$
    n = ImageView_Fullscreen(command_str)
    At one point I was able to bring up the WinXP image viewer but could not get the file name. I can't find any documentation on how to call this function. I don't think I have the declaration correct and I'm guessing I need to "dummy up" the file name from the command line in a particular way.

  • #2
    No, it's wrong. It's important to note that no native API calls use "As String" as a parameter* (if they do exist, I've never come across one in 12 years of Windows programming).

    *VB calls do not count, as they use translation from STRING to ASCII internally.

    This is the correct DECLARE you need to call the function:

    Declare Function ImageView_Fullscreen Alias "ImageView_Fullscreen" Lib "shimgvw.dll" (ByRef pFileName As Asciiz) As Long
    You also do not need to include the path, since the DLL is already in the Windows (system) folder. | Slam DBMS | PrpT Control | Other Downloads | Contact Me


    • #3
      DECLARE FUNCTION ImageView_Fullscreen LIB "shimgvw.dll" ALIAS "ImageView_Fullscreen" (BYVAL command_str AS STRING) AS LONG


      • #4
        using the "ByRef pFileName As Asciiz" from the first post I got a crash. using the BYVAL declaration from the 2nd post doesn't seem to do anything at all. The only way I have been able to make it work is by using the SHELL command but that doesn't seem like a very clean way to do it. Any suggestions?

        DECLARE FUNCTION ImageView_Fullscreen LIB "shimgvw.dll" ALIAS "ImageView_Fullscreen" (BYVAL file_name AS STRING) AS LONG
        LOCAL AStr, file_name AS STRING
        LOCAL rval AS LONG
        'AStr = "rundll32.exe shimgvw.dll,ImageView_Fullscreen "
        file_name = COMMAND$
        'This works
        'shell AStr + file_name
        'This doesn't
        rval = ImageView_Fullscreen(file_name)


        • #5
          And this?

          Local n As Long
          Local command_str As String
          command_str = "C:\.............\image1.png"
          n = Shell( "rundll32.exe shimgvw.dll,ImageView_Fullscreen " & command_str, %SW_SHOWMAXIMIZED )


          • #6
            I suspect that would work as well but I was trying to avoid using the SHELL function / statement. I found some mentions of DDE. Maybe I am missing something.


            • #7
              1) I used the ..A call (the alias) and the window came up but without a file.
              That's odd..

              2) it seems that the library also has a com interface.

              This *should* work but doesn't:
                  Local o As Dispatch
                  Local v As Variant
                  Local v1 As Variant
                  Set o = New Dispatch In "Preview.Preview"    
                  v = "C:\.....BEEMW.jpg"
                  v1 = 0
                  Object Call o.ShowFile( v, v1 )
                  'MsgBox  Str$( IsObject( o ) )


              • #8
                You mean you want to call your function from your own program?

                Functions which work with RUNDLL32 must have the following prototype which you could have found in your WinAPI reference:
                The Run DLL utility (Rundll32.exe) included in Windows enables you to call functions exported from a 32-bit DLL. These functions must have the following syntax:
                void CALLBACK EntryPoint(
                  HWND hwnd,        // handle to owner window
                  HINSTANCE hinst,  // instance handle for the DLL
                  LPTSTR lpCmdLine, // string the DLL will parse
                  int nCmdShow      // show state
                So you need a DECLARE for the way the function must be defined...
                DECLARE FUNCTION ImageView_Fullscreen ALIAS "ImageView_FullScreen"  LIB "shimgvw.dll" ALIAS "ImageView_Fullscreen"  _
                   (BYVAL hWnd AS LONG, _
                    BYVAL hinst AS LONG,_
                    sz  AS ASCIIZ, _
                    BYVAL iCmdShow AS LONG) AS LONG
                Then you just set it up and call it...
                FUNCTION PBMAIN() AS LONG
                  LOCAL sz AS ASCIIZ * %MAX_PATH, iret as long
                  LOCAL hWnd AS LONG, hInst AS LONG, icmdShow AS LONG
                   hWnd        = GetDesktopWindow()
                   hINst        = GetModuleHandle ("shimgvw.dll") * 
                   iCmdShow  = %SW_SHOW
                   sz             = "C:\folder\...\amd,sadsmand\nmdnamsnd.png"
                   iRet = ImageView_Fullscreen (hWnd, hINst, sz, iCmdShow) 
                END FUNCTION
                The doc is not real clear if you need an instance handle for the DLL file or for the owning program. If above does not work try making hinst = GetModuleHandle(BYVAL %NULL) and try again.

                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]


                • #9
                  Got it to work with
                  DECLARE FUNCTION ImageView_Fullscreen LIB "shimgvw.dll" ALIAS "ImageView_Fullscreen" (BYVAL DWORD) AS LONG
                  FUNCTION PBMAIN () AS LONG
                  LOCAL file_name AS STRING
                  LOCAL rval AS LONG
                  file_name = UCODE$(COMMAND$) + $NUL
                  rval = ImageView_Fullscreen(STRPTR(file_name))
                  END FUNCTION
                  Apparently requires a two byte string format


                  • #10
                    Originally posted by Edwin Knoppert View Post
                    2) it seems that the library also has a com interface.

                    This *should* work but doesn't:
                        Local o As Dispatch
                        Local v As Variant
                        Local v1 As Variant
                        Set o = New Dispatch In "Preview.Preview"    
                        v = "C:\.....BEEMW.jpg"
                        v1 = 0
                        Object Call o.ShowFile( v, v1 )
                        'MsgBox  Str$( IsObject( o ) )

                    It is a visual ActiveX control, so you have to provide a host.

                    The following example demonstrates how to embed the Preview control (remember to change the path and name of the picture to load).

                    #COMPILE EXE
                    #DIM ALL
                    #DEBUG ERROR ON
                    #INCLUDE "WIN32API.INC"
                    %IDC_PREVIEW = 1001
                    ' ========================================================================================
                    ' ATL functions
                    ' ========================================================================================
                    DECLARE FUNCTION AtlAxWinInit LIB "ATL.DLL" ALIAS "AtlAxWinInit" () AS LONG
                    DECLARE FUNCTION AtlAxGetControl LIB "ATL.DLL" ALIAS "AtlAxGetControl" (BYVAL hWnd AS DWORD, BYREF pp AS DWORD) AS DWORD
                    ' ========================================================================================
                    ' The IUnknown::AddRef method increments the reference count for an interface on an object. It
                    ' should be called for every new copy of a pointer to an interface on a given object.
                    ' ========================================================================================
                    FUNCTION IUnknown_AddRef (BYVAL pthis AS DWORD PTR) AS DWORD
                        LOCAL DWRESULT AS LONG
                        IF ISFALSE pthis THEN EXIT FUNCTION
                        CALL DWORD @@pthis[1] USING IUnknown_AddRef(pthis) TO DWRESULT
                        FUNCTION = DWRESULT
                    END FUNCTION
                    ' ========================================================================================
                    ' Puts the address of an object in a variant and marks it as containing a dispatch variable
                    ' ========================================================================================
                    SUB AtlMakeDispatch (BYVAL lpObj AS DWORD, BYREF vObj AS VARIANT) EXPORT
                       LOCAL lpvObj AS VARIANTAPI PTR                 ' Pointer to a VARIANTAPI structure
                       LET vObj = EMPTY                               ' Make sure is empty to avoid memory leaks
                       lpvObj = VARPTR(vObj)                          ' Get the VARIANT address
                       @lpvObj.vt = %VT_DISPATCH                      ' Mark it as containing a dispatch variable
                       @lpvObj.vd.pdispVal = lpObj                    ' Set the dispatch pointer address
                       IUnknown_AddRef lpObj                          ' Increment the reference counter
                    END SUB
                    ' ========================================================================================
                    ' Main
                    ' ========================================================================================
                    FUNCTION WINMAIN (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS ASCIIZ PTR, BYVAL nCmdShow AS LONG) AS LONG
                       LOCAL hWndMain AS dword
                       LOCAL hCtl AS DWORD
                       LOCAL hFont AS DWORD
                       LOCAL wcex AS WndClassEx
                       LOCAL szClassName AS ASCIIZ * 80
                       LOCAL rc AS RECT
                       LOCAL szCaption AS asciiz * 255
                       LOCAL nLeft AS LONG
                       LOCAL nTop AS LONG
                       LOCAL nWidth AS LONG
                       LOCAL nHeight AS LONG
                       AtlAxWinInit   ' Initialize ATL
                       hFont = GetStockObject(%ANSI_VAR_FONT)
                       ' Register the window class
                       szClassName        = "MyClassName"
                       wcex.cbSize        = SIZEOF(wcex)
                      = %CS_HREDRAW OR %CS_VREDRAW
                       wcex.lpfnWndProc   = CODEPTR(WndProc)
                       wcex.cbClsExtra    = 0
                       wcex.cbWndExtra    = 0
                       wcex.hInstance     = hInstance
                       wcex.hCursor       = LoadCursor (%NULL, BYVAL %IDC_ARROW)
                       wcex.hbrBackground = %COLOR_3DFACE + 1
                       wcex.lpszMenuName  = %NULL
                       wcex.lpszClassName = VARPTR(szClassName)
                       wcex.hIcon         = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' Sample, if resource icon: LoadIcon(hInst, "APPICON")
                       wcex.hIconSm       = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) ' Remember to set small icon too..
                       RegisterClassEx wcex
                       ' Window caption
                       szCaption = "Preview Demo"
                       ' Retrieve the size of the working area
                       SystemParametersInfo %SPI_GETWORKAREA, 0, BYVAL VARPTR(rc), 0
                       ' Calculate the position and size of the window
                       nWidth  = (((rc.nRight - rc.nLeft)) + 2) * 0.95   ' 95% of the client screen width
                       nHeight = (((rc.nBottom - rc.nTop)) + 2) * 0.95   ' 95% of the client screen height
                       nLeft   = ((rc.nRight - rc.nLeft) \ 2) - nWidth \ 2
                       nTop    = ((rc.nBottom - rc.nTop) \ 2) - (nHeight \ 2)
                       ' Create a window using the registered class
                       hWndMain = CreateWindowEx(%WS_EX_CONTROLPARENT, _           ' extended style
                                                 szClassName, _                    ' window class name
                                                 szCaption, _                      ' window caption
                                                 %WS_OVERLAPPEDWINDOW OR _
                                                 %WS_CLIPCHILDREN, _               ' window style
                                                 nLeft, _                          ' initial x position
                                                 nTop, _                           ' initial y position
                                                 nWidth, _                         ' initial x size
                                                 nHeight, _                        ' initial y size
                                                 %NULL, _                          ' parent window handle
                                                 0, _                              ' window menu handle
                                                 hInstance, _                      ' program instance handle
                                                 BYVAL %NULL)                      ' creation parameters
                       ' Create the Preview control
                       hCtl = CreateWindowEx(%NULL, _                                             ' extended styles
                                             "AtlAxWin", _                                        ' class name
                                             "Preview.Preview.1", _                               ' caption
                                             %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR _    ' window styles
                                             %WS_TABSTOP, _
                                             0, 0, _                                              ' left, top
                                             0, 0, _                                              ' width, height
                                             hWndMain, %IDC_PREVIEW, _                            ' handle of parent, control ID
                                             hInstance, BYVAL %NULL)                              ' handle of instance, creation parameters
                       ' Get the interface pointer of the Preview control
                       LOCAL pUnk AS DWORD
                       AtlAxGetControl(hCtl, pUnk)
                       ' Make a dispatch variant from it to be able to use PB automation
                       LOCAL vVar AS VARIANT
                       LOCAL oPreview AS DISPATCH
                       AtlMakeDispatch(pUnk, vVar)
                       SET oPreview = vVar
                       vVar = EMPTY
                       ' Load the file
                       LOCAL vName AS VARIANT
                       LOCAL vSelectCount AS VARIANT
                       ' --> Change me!
                       vName = "C:\Documents and Settings\Pepe\Mis documentos\Mis imágenes\Capture.jpg"
                       vSelectCount = 0 AS LONG
                       OBJECT CALL oPreview.ShowFile(vName, vSelectCount)
                       ' Show the window
                       ShowWindow hWndMain, nCmdShow
                       UpdateWindow hWndMain
                       ' Message handler loop
                       LOCAL Msg AS tagMsg
                       WHILE GetMessage(Msg, %NULL, 0, 0)
                          IF ISFALSE IsDialogMessage(hWndMain, Msg) THEN
                             TranslateMessage Msg
                             DispatchMessage Msg
                          END IF
                       FUNCTION = msg.wParam
                    END FUNCTION
                    ' ****************************************************************************************
                    ' ****************************************************************************************
                    ' Main Window procedure
                    ' ****************************************************************************************
                       LOCAL rc AS RECT
                       SELECT CASE wMsg
                          CASE %WM_COMMAND
                             SELECT CASE LOWRD(wParam)
                                CASE %IDCANCEL
                                   IF HIWRD(wParam) = %BN_CLICKED THEN
                                      SendMessage hWnd, %WM_CLOSE, wParam, lParam
                                      FUNCTION = 0
                                      EXIT FUNCTION
                                   END IF
                             END SELECT
                          CASE %WM_SYSCOMMAND
                             ' Capture this message and send a WM_CLOSE message
                             IF (wParam AND &HFFF0) = %SC_CLOSE THEN
                                SendMessage hWnd, %WM_CLOSE, wParam, lParam
                                EXIT FUNCTION
                             END IF
                          CASE %WM_DESTROY
                             PostQuitMessage 0
                             EXIT FUNCTION
                          CASE %WM_SIZE
                             IF wParam <> %SIZE_MINIMIZED THEN
                                GetClientRect hWnd, rc
                                MoveWindow GetDlgItem(hWnd, %IDC_PREVIEW), rc.nLeft, rc.nTop, rc.nRight - rc.nLeft, rc.nBottom - rc.nTop, %TRUE
                             END IF
                       END SELECT
                       FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
                    END FUNCTION


                    • #11
                      1) I tried the unicode as well but on the ..W function.
                      The $nul should not be needed but maybe this is the clue?

                      2) And yes, i almost tried it with ATL but i thought it was a stand alone app, ha!


                      • #12
                        >Got it to work with

                        I don't know how that worked if that function was designed for use with RunDll32.Exe, since the procedure header does not match the doc for "rundll" functions.

                        Oh, wait a minute ... it looks you never got it work correctly using rundll32.exe.

                        The part about needing a Unicode filename is because that's the way the function author wrote it.
                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]