News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

DLL's and dialog resources

Started by MickD, January 30, 2006, 12:30:49 AM

Previous topic - Next topic

MickD

Hi All,
Could someone explain the steps or win32 api function/s required to include a dialog in a dynamically linked DLL. I understand that there may be resource conflicts if someone loads my dll at runtime and it loads a dialog that may have similar resource ID's. I have a copy of Petzolds' but I'm not sure which function to look for  :(

TIA,
Mick

MichaelW

After a quick test put together from MASM32 examples I determined that this can be done with an In Memory Dialog (see \masm32\help\dialogs.hlp).
The DLL code (testdll.asm):

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc

    DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD

    .data?
        hWnd      dd ?
        hInstance dd ?
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
LibMain proc instance:DWORD,reason:DWORD,unused:DWORD
    .if reason == DLL_PROCESS_ATTACH
      push instance
      pop hInstance
      mov eax, TRUE
    .elseif reason == DLL_PROCESS_DETACH
    .elseif reason == DLL_THREAD_ATTACH
    .elseif reason == DLL_THREAD_DETACH
    .endif
    ret
LibMain endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
TestProc proc
    Dialog "Blank Dialog", \                ; caption
           "MS Sans Serif",10, \            ; font,pointsize
            WS_OVERLAPPED or \              ; styles for
            WS_SYSMENU or DS_CENTER, \      ; dialog window
            3, \                            ; number of controls
            50,50,155,100, \                ; x y co-ordinates
            1024                            ; memory buffer size
    DlgButton "OK",WS_TABSTOP,106,5,40,13,IDOK
    DlgButton "Cancel",WS_TABSTOP,106,20,40,13,IDCANCEL
    DlgStatic "MASM32 Dialog",SS_LEFT,5,5,60,9,100
    CallModalDialog hInstance,0,DlgProc,NULL
    ret
TestProc endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
DlgProc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD 
    Switch uMsg
      Case WM_INITDIALOG
        invoke SendMessage,hWin,WM_SETICON,1,
                           FUNC(LoadIcon,NULL,IDI_ASTERISK)
        m2m hWnd, hWin
        return 1
      Case WM_COMMAND
        Switch wParam
          Case IDOK
            invoke MessageBox,hWnd,SADD("You clicked OK"),
                              SADD("Hi"),MB_OK or MB_ICONINFORMATION
          Case IDCANCEL
            jmp quit_dialog
        EndSw
      Case WM_CLOSE
        quit_dialog:
         invoke EndDialog,hWin,0
    EndSw
    return 0
DlgProc endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end LibMain


And a console app to load the DLL and call the dialog.

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      hLib      dd 0
      libName   db "testdll.dll",0
      FuncName  db "TestProc",0
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke LoadLibrary,ADDR libName
    mov hLib, eax
    invoke GetProcAddress,hLib,ADDR FuncName
    call eax
    invoke FreeLibrary,hLib
    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
eschew obfuscation

MickD

Thanks Michael,
I'll digest that and read the help files you mentioned and let you know how I get on.

I was hoping to use a .rc file from an editor but I guess I could tranlate that into the dll itself without too much trouble.
Cheers,
Mick.

sluggy

IIRC, the hInstance parameter to the various create dialog APIs takes the handle to the dll containing the resource - which means it is okay to have resources with the same id - just make sure you don't have the same id twice in the same dll or module.

MusicalMike

Did you ever notice that hinstance always seems to be the base address of a standard executable image? I believe its 0x00400000, but I might be wrong. Baring this in mind, when you have something that requires an hinstance value, be it a data structure like the WNDCLASS, or even the LoadIcon function, passing the above mentioned value will work. Infact, as long as you know this value you don't need to allocate global memory in order to store the hinstance, because if you always know what it is, you can pass the constant value 0x00400000. I am not sure if this holds true for dll and lib files.

Tedd

Quote from: MusicalMike on January 31, 2006, 05:35:37 PM
Did you ever notice that hinstance always seems to be the base address of a standard executable image? I believe its 0x00400000, but I might be wrong. Baring this in mind, when you have something that requires an hinstance value, be it a data structure like the WNDCLASS, or even the LoadIcon function, passing the above mentioned value will work. Infact, as long as you know this value you don't need to allocate global memory in order to store the hinstance, because if you always know what it is, you can pass the constant value 0x00400000. I am not sure if this holds true for dll and lib files.

While that seems to be true right now, it may not be in the future. And in the grand scheme of things, is it really worth saving on a whole dword? (Yes, I know they're so rare these days :P)
No snowflake in an avalanche feels responsible.

donkey

Quote from: MusicalMike on January 31, 2006, 05:35:37 PM
Did you ever notice that hinstance always seems to be the base address of a standard executable image? I believe its 0x00400000, but I might be wrong. Baring this in mind, when you have something that requires an hinstance value, be it a data structure like the WNDCLASS, or even the LoadIcon function, passing the above mentioned value will work. Infact, as long as you know this value you don't need to allocate global memory in order to store the hinstance, because if you always know what it is, you can pass the constant value 0x00400000. I am not sure if this holds true for dll and lib files.

Yes, this is true for now but it is not guaranteed to reamin this way. In reality the instance handle is a hold-over from 16 bit windows, there are no longer any "instances" of an application since each runs in it's own virtual memory space and so is the only instance it can see. But because of type casting it remained as part of Windows 32 bit, however MS is less concerned about 16 bit compatibility with each subsequent version of Windows and may just drop it one day.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

hutch--

The only real value of the instance handle in either an EXE or DLL file is for a variety of function to know the starting address in memory of the application so they can find things like resources. While it is true that current EXE files use 400000h as a starting address, a DLL has its own start address which can be changed dynamically depending on what load address is available when the DLL is first called and this is certainly NOT 400000h.

Now with Micks question, dialogs must have a unique identification to be used in the same app, either as local resources or from within a DLL but once you have the dialog with a unique ID, the controls used on the dialog can use duplicate ID identifiers with no problems as they are associated with a seperate window (dialog).
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

MickD

Quote from: hutch-- on February 01, 2006, 12:07:29 AM
Now with Micks question, dialogs must have a unique identification to be used in the same app, either as local resources or from within a DLL but once you have the dialog with a unique ID, the controls used on the dialog can use duplicate ID identifiers with no problems as they are associated with a seperate window (dialog).

I guess that was what I was getting at, I do some programming with autocad using c++ dll's and if you want to include a dialog resource you have to handle your resources.
A quote from the help doc's
Quote
Resource management is an important consideration when designing an ObjectARX application that uses an MFC library shared with AutoCAD and other applications.

You must insert your module state (using CDynLinkLibrary) into the chain that MFC examines when it performs operations such as locating a resource. However, it is strongly recommended that you explicitly manage your application's resources so that they will not conflict with other resources from AutoCAD or other ObjectARX applications.

To explicitly set resources

Before taking any steps that would cause MFC to look for your resource, call the AFX function AfxSetResourceHandle() to set the custom resource as the system default.
Before setting the system resource to your resource, call AfxGetResourceHandle() to get and store the current system resource handle.
Immediately after performing any functions that require the custom resource, the system resource should be reset to the resource handle previously saved.
When calling AutoCAD API functions or invoking AutoCAD commands that need AutoCAD's resources, such as acedGetFileD(), be sure to set the resource back to AutoCAD before making the function call. Restore your application's resource afterwards. Use acedGetAcadResourceInstance() to get AutoCAD's resource handle.

So other than an in memory dialog, how could you be sure that your dialog ID is unique or would you handle the resources as mentioned above.
IOW what is the win32 equivelant of 'AfxGetResourceHandle' or is that the handle returned using the normal 'create' functions?
Sorry if this is simple stuff, I've just got to get rid of all the fluff you 'have' to use in the HLL's, I'm actually finding it a lot simpler in asm working without it ;)