Passing HWND into a DLL

Hey all. I hit a problem in my work today and am not 100% on how to do something like this. I have a library function that resides in a DLL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef _DXRENDERSYSTEM_H_
#define _DXRENDERSYSTEM_H_

#define VC_EXTRALEAN
#define DLL_IMPORT __declspec(dllimport)
#define DLL_EXPORT __declspec(dllexport)
#ifndef __cplusplus
extern "C"
#endif

#include <d3d9.h>
//#include <d3dx9.h>

//Temporally link librarys here.
#pragma comment(lib, "d3d9.lib")
//#pragma comment(lib, "d3dx9.lib")

class DLL_EXPORT DxRenderer
{
public:	
//Function stored in DLL.
HRESULT _CreateResources(HWND hWnd);
};


My problem is this: The function HRESULT _CreateResources(HWND hWnd)Requires that the handle to the window is used to create the resources required. The Window is defined in a separate project that uses the DLL for the main application. Is there anyway I could create the window in the application, pass the HANDLE to the dll file so it can create the resources, and then if needed pass back any information that might be encountered later on from the dll to the main application.

I'm sorry if that is a bit confusing. If any more information is needed please ask.

Thanks,
Strych.

EDIT: The entry point is responsible for creating the handle:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*==============================================================
	INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpszCmdLine, int nShowCmd)
	---------------
	The entry point for windows and the application.
==============================================================*/
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	// the handle for the window
    HWND hWnd;

    WNDCLASSEX wc;

    // clear out the window class for use
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    // fill in the struct with the needed information
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WinProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = "TetrisDxClass";

    // register the window class
    RegisterClassEx(&wc);

    // create the window and use the result as the handle
    hWnd = CreateWindowEx(NULL,
                          "TetrisDxClass",    // name of the window class
                          "TetrisDx",   // title of the window
                          WS_OVERLAPPEDWINDOW,    // window style
                          300,    // x-position of the window
                          300,    // y-position of the window
                          500,    // width of the window
                          400,    // height of the window
                          NULL,    // we have no parent window, NULL
                          NULL,    // we aren't using menus, NULL
                          hInstance,    // application handle
                          NULL);    // used with multiple windows, NULL
// Initialize Direct3D
	if( SUCCEEDED( /*_CreateResources( hWnd*/ ) ) )
	{
            // Show the window
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

            // Enter the message loop
            MSG msg;
            ZeroMemory( &msg, sizeof( msg ) );
            while( msg.message != WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
					//DxRenderCall->_RenderScene();
            }
        }

    // return this part of the WM_QUIT message to Windows
    return msg.wParam;
}


Also I get the feeling this is were a Callback function could be used, but I'm not 100% on how to go about that. If a callback function would work, could someone please post some code, or point me in the right direction?
Last edited on
What are the resources that you need to pass back?

Are you using the term "resources" in the standard WIN32 sense of icons, menus, dialogs, ... ?

Andy

P.S. This bit of code looks wrong

#ifndef __cplusplus
extern "C"
#endif
I'm sorry resources wasn't quite the right term. The _CreateResources(HWND hWnd) function takes the handle to the window and uses it to create the Direct3D9 rendering object, which is then in return used to create the rendering device. Here is the source code for the function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
*==============================================================
	HRESULT DxRenderer::_CreateResources()
	
	Create the resources and rendering device used by DirectX.
==============================================================*/
HRESULT DxRenderer::_CreateResources(HWND hWnd)
{
	//Create the Direct3D object. The object is used to create
	//the rendering device.
	if(NULL == (DxD3D = Direct3DCreate9(D3D_SDK_VERSION)))
		return E_FAIL;


	D3DPRESENT_PARAMETERS DxD3Dpp;
	ZeroMemory(&DxD3Dpp, sizeof(DxD3Dpp));
		DxD3Dpp.Windowed		 = TRUE;
		DxD3Dpp.SwapEffect		 = D3DSWAPEFFECT_DISCARD;
		DxD3Dpp.BackBufferFormat = D3DFMT_UNKNOWN;

	//Take the settings we configured and create the Direct3D
	//rendering device.
	if(FAILED(DxD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&DxD3Dpp, &DxD3D9Device)))
	{
		return E_FAIL;
	}

	return S_OK;
}


Also if you don't mind me asking, what looks wrong about
1
2
3
#ifndef __cplusplus
extern "C"
#endif 


Strych.

EDIT: Doh, I just realized how
1
2
3
#ifndef __cplusplus
extern "C"
#endif 

is wrong. Thank you for pointing that out, as you probably just saved me an hour of headache.
Last edited on
you mean you should #endif the first #ifndef and then continue with the command? or is there's something else? i don't really understand about this kinda stuff...
Yes you do need to #endif the first #ifnedef but the mistake with that code is that I ended the #ifndef right after the extern "C". I need to #endif at the very end of the file.
extern C is used when you're compling C++ code, so you need to invert the logic to #ifdef __cplusplus

Do you want to provide access to (some of) the interfaces stored in DxD3D, DxD3Dpp, DxD3D9Device (all member variables of DxRenderer, I presume?) Or do you want your DLL to do all Direct3D related work?

I have never used callbacks with Direct3D -- I've only ever called it to render things when I want it to -- so I can't help you with that question. Hopefully there's someone with real Direct3D experience about!

Andy

P.S. I take it that you are already familiar with COM's reference counting rules?
@strychnine: oh that, i thought it should be like:
1
2
3
4
5
...
#endif
#ifndef __cplusplus
extern "C"
#endif 


but i guess it would have the same result...

@andy: what's COM?

@both and other: how to create a .dll file anyway? and how to use 'em?
what's COM?

In this contexts, it's the Component Object Model

http://en.wikipedia.org/wiki/Component_Object_Model

The pointer returned by Direct3DCreate9 is a COM interface. They are often, but not always implemented using C++ (you can use C#, VB, ...). When you use COM obhects you need to understand how AddRef() and Release() work, and also QueryInterface().

how to create a .dll file anyway? and how to use 'em?

Too big a topic for a post! But this Microsoft KB article might answer some of your qestions. It includes a simple example.

What is a DLL?
http://support.microsoft.com/kb/815065

I create DLLs using the Visual C++ Std's app wizard. I believe it is also possible with Visual C++ Express, but I don't know the details.

Other modern, Windows friendly IDEs should provide similar functionality. I know CodeLite does!
Last edited on
What I don't see in WinMain() is a call to CoInitialize(). Is there a substitute function when using DirectX? I ask 'cause I know nothing about DirectX, but knowing COM, I know the apartment must be initialized and I don't see CoInitialize() or CoInitializeEx() anywhere in WinMain().
I hadn't really planned to give an access interface to the objects, but I can see were it might be needed later on down the road. Right now the DLL is just doing all the leg work for the application, i.e. take the window handle from the main window and using it to create the objects, etc.

@CHIPP: COM is the model Microsoft uses for DirectX. You can think of COM's as Lego's. Each one is independent from the others, each COM only holds and is aware of the information used by that COM, but you can put the COM's together to create something big. I hope that helps.

As far as DLL creation and uses go: A dll is an application extension. You could statically link you lib's together and pack them all into one exe, or you can dynamically link your exe in which the library's are exported to .DLL files and used by the program. For game programming this is the preferred way for many reasons. There are a few ways of creating them: You can do it andy's way were you use the wizard, or you can do it my way.
@webJose: As far as I know you don't have to call anything when using DirectX. I'm almost 90% DirectX does this automatically behind the scenes, or at least that's how it usually works in most cases.

If I'm remembering right: as long as you can pass the required arguments to what ever function is creating and initializing the COM objects, DirectX should be able to do everything else. I hope that helps ;D I'm not 100% on how to explain such a confusing topic.
Last edited on
@webJose I think, like strychnine213, that Direct3D must be calling CoInit' for you (as part of Direct3DCreate9)

It would be easy enough to test, if you want to (I don't have any Direct3D code lying around...) When called a second time, CoInit' will return S_FALSE (= 1 / "The COM library is already initialized on this thread.") or RPC_E_CHANGED_MODE, if you called specfying a different concurrency model.

But I guess there is a possibility that they follow COM rules without being reliant on COM.

Andy

P.S. All calls to CoInit' should be balanced by calls to CoUnit'
Last edited on
I think andy might be right. I know that DirectX does alot of stuff behind the scenes to make it a bit more "user friendly".

EDIT: I gave that question a quick look over and it does appear that DirectX auto calls that when it registers the created device.
Last edited on
You have to include <windows.h> to get the HWND struct which is used for the handle for the window.
Topic archived. No new replies allowed.