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
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
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.
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.
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.
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)
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.
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).
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 ;)